/*
OpenMQTTGateway - ESP8266 or Arduino program for home automation
Act as a wifi or ethernet gateway between your 433mhz/infrared IR signal/BLE and a MQTT broker
Send and receiving command by MQTT
This gateway enables to:
- publish MQTT data to a different topic related to BLE devices rssi signal
Copyright: (c)Florian ROBERT
This file is part of OpenMQTTGateway.
OpenMQTTGateway is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenMQTTGateway is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Thanks to wolass https://github.com/wolass for suggesting me HM 10 and dinosd https://github.com/dinosd/BLE_PROXIMITY for inspiring me how to implement the gateway
*/
#ifdef ZgatewayBT
#include
#define STRING_MSG "OK+DISC:"
#define RESPONSE_MSG "OK+DISIS"
#define RESP_END_MSG "OK+DISCE"
#define SETUP_MSG "OK+RESET"
SoftwareSerial softserial(BT_RX, BT_TX);
String returnedString = "";
unsigned long timebt = 0;
void setupBT() {
softserial.begin(9600);
softserial.print(F("AT+ROLE1"));
delay(100);
softserial.print(F("AT+IMME1"));
delay(100);
softserial.print(F("AT+RESET"));
delay(100);
}
#ifndef ZgatewayBT_stable // published for test only, if you want to test mi flora integration uncomment ZgatewayBT_stable in config_BT
#define QUESTION_MSG "AT+DISA?"
boolean BTtoMQTT() {
//extract serial data from module in hexa format
while (softserial.available() > 0) {
int a = softserial.read();
if (a < 16) {
returnedString = returnedString + "0";
}
returnedString = returnedString + String(a,HEX);
}
if (millis() > (timebt + TimeBtw_Read)) {//retriving data
timebt = millis();
#ifdef ESP8266
yield();
#endif
if (returnedString != "") {
size_t pos = 0;
while ((pos = returnedString.lastIndexOf(delimiter)) != std::string::npos) {
#ifdef ESP8266
yield();
#endif
String token = returnedString.substring(pos);
returnedString.remove(pos,returnedString.length() );
char token_char[token.length()+1];
token.toCharArray(token_char, token.length()+1);
char mac_adress[13];
trc(F("mac_adress "));
extract_char(token_char, mac_adress, delimiter_length ,12,true);
char device_type[3];
trc(F("device_type "));
extract_char(token_char, device_type, delimiter_length+12 ,2,false);
int rssi;
trc(F("rssi "));
extract_int(token_char, rssi, delimiter_length +12+2 ,2,false);
char val[12];
sprintf(val, "%d", rssi);
String mactopic(mac_adress);
mactopic = subjectBTtoMQTT + mactopic;
client.publish((char *)mactopic.c_str(),val);
int rest_data_length;
trc(F("rest_data_length "));
extract_int(token_char, rest_data_length, delimiter_length+12+2+2 ,2,false);
char rest_data[rest_data_length*2];
trc(F("rest_data "));
extract_char(token_char, rest_data, delimiter_length+12+2+2+2 ,rest_data_length*2,false);
char sensor_type[5];
trc(F("sensor_type "));
extract_char(rest_data, sensor_type, 10 ,4,true);
if (strcmp(sensor_type, "fe95") == 0) process_miflora_data(rest_data,mac_adress);
}
returnedString = ""; //init data string
}
softserial.print(F(QUESTION_MSG));
return true;
}else{
return false;
}
}
void process_miflora_data(char * rest_data, char * mac_adress){
char tmp_rest_data_length[1];
memcpy( tmp_rest_data_length, &rest_data[51], 1 );
int data_length = ((int)strtol(tmp_rest_data_length, NULL, 16)*2)+1;
char rev_data[data_length];
char data[data_length];
memcpy( rev_data, &rest_data[52], data_length );
rev_data[data_length] = '\0';
// reverse data order
revert_hex_data(rev_data, data, data_length);
int value = strtol(data, NULL, 16);
trc(String(value));
char val[12];
sprintf(val, "%d", value);
String mactopic(mac_adress);
mactopic = subjectBTtoMQTT + mactopic;
// following the value of digit 47 we determine the type of data we get from the sensor
switch (rest_data[47]) {
case '9' :
mactopic = mactopic + "/" + "fertilisation";
break;
case '4' :
mactopic = mactopic + "/" + "temperature_Cx10";
break;
case '7' :
mactopic = mactopic + "/" + "lux";
break;
case '8' :
mactopic = mactopic + "/" + "humidity";
break;
default:
trc("can't read values");
}
client.publish((char *)mactopic.c_str(),val);;
trc(String(val));
}
void revert_hex_data(char * in, char * out, int l){
//reverting array 2 by 2 to get the data in good order
int i = l-2 , j = 0;
while ( i != -2 ) {
if (i%2 == 0) out[j] = in[i+1];
else out[j] = in[i-1];
j++;
i--;
}
out[l-1] = '\0';
}
void extract_char(char * token_char, char * subset, int start ,int l, boolean reverse){
char tmp_subset[l+1];
memcpy( tmp_subset, &token_char[start], l );
tmp_subset[l] = '\0';
if (reverse) revert_hex_data(tmp_subset, subset, l+1);
else strncpy( subset, tmp_subset , l+1);
Serial.println(subset);
}
void extract_int(char * token_char, int & subsetint, int start ,int l, boolean reverse ){
char tmp_subset[l+1];
char subset[l+1];
memcpy( tmp_subset, &token_char[start], l );
tmp_subset[l] = '\0';
if (reverse) revert_hex_data(tmp_subset, subset, l+1);
else strncpy( subset, tmp_subset, l+1 );
subsetint = (int)strtol(subset, NULL, 16);
Serial.println(subsetint);
}
#endif
#ifdef ZgatewayBT_stable
#define QUESTION_MSG "AT+DISI?"
boolean BTtoMQTT() {
while (softserial.available() > 0) {
#ifdef ESP8266
yield();
#endif
String discResult = softserial.readString();
if (discResult.indexOf(STRING_MSG)>=0){
discResult.replace(RESPONSE_MSG,"");
discResult.replace(RESP_END_MSG,"");
float device_number = discResult.length()/78.0;
if (device_number == (int)device_number){ // to avoid publishing partial values we detect if the serial data has been fully read = a multiple of 78
trc(F("Sending BT data to MQTT"));
#ifdef ESP8266
yield();
#endif
for (int i=0;i<(int)device_number;i++){
String onedevice = discResult.substring(0,78);
onedevice.replace(STRING_MSG,"");
String mac = onedevice.substring(53,65);
String rssi = onedevice.substring(66,70);
String mactopic = subjectBTtoMQTT + mac;
trc(mactopic + " " + rssi);
client.publish((char *)mactopic.c_str(),(char *)rssi.c_str());
discResult = discResult.substring(78);
}
return true;
}
}
if (discResult.indexOf(SETUP_MSG)>=0)
{
trc(F("Connection OK to HM-10"));
}
}
if (millis() > (timebt + TimeBtw_Read)) {//retriving value of adresses and rssi
timebt = millis();
#ifdef ESP8266
yield();
#endif
softserial.print(F(QUESTION_MSG));
}
return false;
}
#endif
#endif