In regards the simple Feed Mode using the MobiusBLE library.
The sketch I posted before isn't working properly, but the one down below was just tested and is working for me.
Let me explain the idea:
The sketch uses the HA/MQTT auto discovery function.
during boot, it will publish 2 initial JSON messages so the HA component can be created automatically:
homeassistant/switch/mobiusBridge/config:
and
homeassistant/sensor/mobiusBridge/config:
It will then send the Feed mode status and the quantity of Mobius Devices found:
homeassistant/switch/mobiusBridge/state: OFF
homeassistant/sensor/mobiusBridge/state: {"qtydevices":2}
Ideally, this should auto create the component in HA similar to the below:
To enable/disable Feed Mode, just turn on/off the "Feed Mode" switch.
Although the switch is now reflecting the new state, please note it takes time to scan and set the scene, but you can monitor the execution using the arduino Serial Monitor.
and lastly, use it at your own risk as I'm not a programmer and this was coded as a simple proof of concept based on @thetastate initial idea and no extensive test was executed.
The sketch I posted before isn't working properly, but the one down below was just tested and is working for me.
Let me explain the idea:
The sketch uses the HA/MQTT auto discovery function.
during boot, it will publish 2 initial JSON messages so the HA component can be created automatically:
homeassistant/switch/mobiusBridge/config:
JSON:
{
"name":"Feed Mode",
"command_topic":"homeassistant/switch/mobiusBridge/set",
"state_topic":"homeassistant/switch/mobiusBridge/state",
"unique_id":"mobius01ad",
"device":{
"identifiers":[ "mobridge01ad" ],
"name":"Mobius"
}
}
and
homeassistant/sensor/mobiusBridge/config:
JSON:
{
"name":"QTY Devices",
"state_topic":"homeassistant/sensor/mobiusBridge/state",
"value_template":"{{ value_json.qtydevices}}",
"unique_id":"qtydev01ae",
"device":{
"identifiers":[ "mobridge01ad" ]
}
}
It will then send the Feed mode status and the quantity of Mobius Devices found:
homeassistant/switch/mobiusBridge/state: OFF
homeassistant/sensor/mobiusBridge/state: {"qtydevices":2}
Ideally, this should auto create the component in HA similar to the below:
To enable/disable Feed Mode, just turn on/off the "Feed Mode" switch.
Although the switch is now reflecting the new state, please note it takes time to scan and set the scene, but you can monitor the execution using the arduino Serial Monitor.
and lastly, use it at your own risk as I'm not a programmer and this was coded as a simple proof of concept based on @thetastate initial idea and no extensive test was executed.
C++:
#include <ESP32_MobiusBLE.h>
#include "ArduinoSerialDeviceEventListener.h"
#include "EspMQTTClient.h"
#include <string>
#include "secrets.h"
#include <ArduinoJson.h>
// Configuration for wifi and mqtt
EspMQTTClient client(
mySSID, // Your Wifi SSID
myPassword, // Your WiFi key
"homeassistant.local", // MQTT Broker server ip
mqttUser, // mqtt username Can be omitted if not needed
mqttPass, // mqtt pass Can be omitted if not needed
"Mobius", // Client name that uniquely identify your device
1883 // MQTT Broker server port
);
char* jsonSwitchDiscovery = "{\
\"name\":\"Feed Mode\",\
\"command_topic\":\"homeassistant/switch/mobiusBridge/set\",\
\"state_topic\":\"homeassistant/switch/mobiusBridge/state\",\
\"unique_id\":\"mobius01ad\",\
\"device\":{\
\"identifiers\":[\
\"mobridge01ad\"\
],\
\"name\":\"Mobius\"\
}}";
char* jsonSensorDiscovery = "{ \
\"name\":\"QTY Devices\",\
\"state_topic\":\"homeassistant/sensor/mobiusBridge/state\",\
\"value_template\":\"{{ value_json.qtydevices}}\",\
\"unique_id\":\"qtydev01ae\",\
\"device\":{\
\"identifiers\":[\
\"mobridge01ad\"\
]\
}\
}";
char* jsonDeviceDiscovery = "{ \
\"state_topic\":\"homeassistant/sensor/%s/state\",\
\"unique_id\":\"%s\",\
\"device\":{\
\"identifiers\":[\
\"%s\"\
],\
\"name\":\"%s\",\
}\
}";
bool prevState = false;
bool currState = false;
bool configPublish = false;
bool firstRun = true;
// wifi and mqtt connection established
void onConnectionEstablished()
{
Serial.println("Connected to MQTT Broker :)");
// Listen for a scene update from mqtt and call the update function
// May need to do this from the loop(). Test.
client.subscribe("homeassistant/switch/mobiusBridge/set", [](const String& feedMode) {
if (feedMode.length() > 0) {
if (feedMode == "ON") {
Serial.printf("INFO: IS this On? %s\n", feedMode);
currState = true;
} else {
Serial.printf("INFO: IS this Off? %s\n", feedMode);
currState = false;
}
configPublish = false;
Serial.printf("INFO: Update device scene from MQTT trigger: %s\n", feedMode);
if (!client.publish("homeassistant/switch/mobiusBridge/state", feedMode)) {
Serial.printf("ERROR: Did not publish Feed Switch");
}
}
});
}
// Define a device buffer to hold found Mobius devices
MobiusDevice deviceBuffer[20];
int deviceCount = 0;
JsonDocument doc;
void setup() {
// connect the serial port for logs
Serial.begin(115200);
while (!Serial);
prevState = !currState;
firstRun = true;
client.enableDebuggingMessages(); // Enable debugging messages sent to serial output
client.enableHTTPWebUpdater(); // Enable the web updater. User and password default to values of MQTTUsername and MQTTPassword. These can be overridded with enableHTTPWebUpdater("user", "password").
// Increase default packet size for HA mqtt json messages
client.setMaxPacketSize(2048);
// Initialize the library with a useful event listener
MobiusDevice::init(new ArduinoSerialDeviceEventListener());
Serial.println("Setup run");
}
void loop() {
// Wait for mqtt and wifi connection
while(!client.isConnected()){client.loop();};
// Loop mqtt
client.loop();
// create buffer to store the Mobius devices
MobiusDevice device = deviceBuffer[0];
if (!configPublish) {
//Scan BLE and MQTT Publish the main config only on boot or on status change
Serial.printf("=========================================================\n");
Serial.printf(" INFO: BLE SCAN + PUBLISHING THE MAIN CONFIG \n");
Serial.printf("=========================================================\n");
//Scan for Mobius devices
int scanDuration = 5; // in seconds
deviceCount = 0;
while (!deviceCount) {
//Scan until at least one device is returned
deviceCount = MobiusDevice::scanForMobiusDevices(scanDuration, deviceBuffer,10);
Serial.printf("INFO: Mobius Devices found: %i\n", deviceCount);
}
if (!client.publish("homeassistant/switch/mobiusBridge/config", jsonSwitchDiscovery)) { //This one is for the switch
Serial.printf("ERROR: Did not publish");
}
if (!client.publish("homeassistant/sensor/mobiusBridge/config", jsonSensorDiscovery)) { //This is for the QTY
Serial.printf("ERROR: Did not publish");
}
configPublish = true;
// delaying without sleeping
unsigned long startMillis = millis();
while (2000 > (millis() - startMillis)) {}
}
/***************************************************************
************ BLE Connection starts here ************
***************************************************************/
//inside the mqtt subscribe function onConnectionEstablished(), it will turn the LED on with digitalWrite(LED_BUILTIN, HIGH);
if (prevState != currState) {
//If Current state is different from previous, publish MQTT state
Serial.printf("INFO: Publishing state");
if (!firstRun){
// Do not connect to device during boot
for (int i = 0; i < deviceCount; i++) {
// connect to each device in buffer to set the new scene
device = deviceBuffer[i];
int tries = 1;
//loop until connected or exit after 10 tries
while(tries<=10){
// Connect, get serialNumber and current scene
Serial.printf("\nINFO: Connect to device number: %i\n", i);
if (device.connect()) {
//Get Current scene
uint16_t sceneId = device.getCurrentScene();
//Convert scene from int to friendly MQTT text
char currScene[2];
sprintf(currScene, "%u", sceneId);
// delaying without sleeping
unsigned long startMillis = millis();
while (1000 > (millis() - startMillis)) {}
/*===============================================
===== Set Scene =====
===============================================*/
if ((sceneId!=1) and (currState) ) {
//Scene is different from feed mode (1), and Feed switch is ON, set device to feed mode
device.setFeedScene();
} else if ((sceneId==1) and !currState) {
//Scene is feed mode (1), and Feed switch is OFF, set device to Normal Schedule
device.runSchedule();
}
//Disconnect from Mobius Device
device.disconnect();
//If connection completed, break the loop
break;
}
else {
tries++;
}
}
//Print error message if didn't connect after 10 tries
if (tries>9) {
ESP_LOGE(LOG_TAG, "ERROR: Failed to connect to device");
}
}
}
char cstr[20];
JsonDocument jsonQtyDev;
jsonQtyDev["qtydevices"] = deviceCount;
serializeJson(jsonQtyDev, cstr);
Serial.printf("INFO: Mobius BLE device count: %i\n", deviceCount);
if (!client.publish("homeassistant/sensor/mobiusBridge/state", cstr)) {
FYI:Serial.printf("ERROR: Did not publish qtyitems");
}
prevState = currState;
}
firstRun = false;
}