Controlling Mobius enabled VorTech pump using 0-10V (and BLE)

Paulo Hanashiro

Community Member
View Badges
Joined
Jun 4, 2013
Messages
56
Reaction score
29
Location
Sydney/Australia
Rating - 0%
0   0   0
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:
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:

1717480706128.png


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;
}
 

iamdan

Community Member
View Badges
Joined
Jul 1, 2022
Messages
67
Reaction score
63
Location
Western Australia
Rating - 0%
0   0   0
My addition to @Paulo Hanashiro's work - Added Control of ESP32S3 RGB Led, MQTT Sensor to Advise if Feed Mode was successful or not - This is so you can either have in Home Assistant the simple sensor it provides or you can code your button to change colours if the operation worked or not etc:


C++:
#include <ESP32_MobiusBLE.h>
#include "ArduinoSerialDeviceEventListener.h"
#include "EspMQTTClient.h"
#include <string>
#include "secrets.h"
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.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
);

// WS2812 LED configuration
#define LED_PIN 48
#define LED_COUNT 1
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

// JSON configurations
char* jsonSwitchDiscovery =  "{\
    \"name\":\"Feed Mode\",\
    \"command_topic\":\"homeassistant/switch/mB/set\",\
    \"state_topic\":\"homeassistant/switch/mB/state\",\
    \"unique_id\":\"m01ad\",\
    \"device\":{\
      \"identifiers\":[\
        \"bridge01ad\"\
      ],\
      \"name\":\"Mobius\"\
         }}";

char* jsonSensorDiscovery =  "{ \
    \"name\":\"Devices\",\
    \"state_topic\":\"homeassistant/sensor/mB/state\",\
    \"value_template\":\"{{ value_json.qtydevices}}\",\
    \"unique_id\":\"dev01ae\",\
    \"device\":{\
      \"identifiers\":[\
        \"bridge01ad\"\
      ]\
      }\
    }";

char* jsonFeedModeStatusDiscovery =  "{ \
    \"name\":\"FM Status\",\
    \"state_topic\":\"homeassistant/sensor/mB/fmstatus\",\
    \"unique_id\":\"status01ae\",\
    \"device\":{\
      \"identifiers\":[\
        \"bridge01ad\"\
      ]\
      }\
    }";

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;

// Function to flash LED with specified color and duration
void flashLED(uint32_t color, int duration) {
  strip.setPixelColor(0, color);
  strip.show();
  delay(duration);
  strip.setPixelColor(0, 0); // Turn off the LED
  strip.show();
}

// wifi and mqtt connection established
void onConnectionEstablished() {
  Serial.println("CONNECTED TO MQTT BROKER :)");
  flashLED(strip.Color(0, 0, 255), 5000); // Flash blue for success
 
  // Listen for a scene update from mqtt and call the update function
  client.subscribe("homeassistant/switch/mB/set", [](const String& feedMode) {
    if (feedMode.length() > 0) {
      if (feedMode == "ON") {
        Serial.printf("INFO: VERIFY SWITCH ON: %s\n", feedMode);
        currState = true;
      } else {
        Serial.printf("INFO: VERIFY SWITCH 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/mB/state", feedMode)) {
        Serial.printf("ERROR: DID NOT PUBLISH FEED SWITCH\n");
        flashLED(strip.Color(255, 0, 0), 15000); // Flash red for error
        client.publish("homeassistant/sensor/mB/fmstatus", "FM ERROR");
        Serial.println("FM Status: ERROR");
      } else {
        if (currState) {
          client.publish("homeassistant/sensor/mB/fmstatus", "FM ON OK");
          Serial.println("FM Status: FM ON OK");
        } else {
          client.publish("homeassistant/sensor/mB/fmstatus", "FM OFF OK");
          Serial.println("FM Status: FM OFF OK");
        }
      }
    }
  });
}

// 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);

  // Initialize the WS2812 LED
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
 
  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 overridden 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();
    flashLED(strip.Color(0, 0, 255), 100); // Flash blue for in-progress
  }

  // 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("INFO: BLE SCAN + PUBLISHING THE MAIN CONFIG \n");
    flashLED(strip.Color(0, 0, 255), 100); // Flash blue for in-progress

    // Scan for Mobius devices
    int scanDuration = 5; // in seconds
    deviceCount = 0;
    flashLED(strip.Color(0, 0, 255), 5000); // Flash blue for in-progress

    while (!deviceCount) {
      // Scan until at least one device is returned
      deviceCount = MobiusDevice::scanForMobiusDevices(scanDuration, deviceBuffer, 10);
      Serial.printf("INFO: DEVICES FOUND: %i\n", deviceCount);
    }

    if (!client.publish("homeassistant/switch/mB/config", jsonSwitchDiscovery)) {  // This one is for the switch
      Serial.printf("ERROR: DID NOT PUBLISH SWITCH\n");
      flashLED(strip.Color(255, 0, 0), 15000); // Flash red for error
    }

    if (!client.publish("homeassistant/sensor/mB/config", jsonSensorDiscovery)) { // This is for the QTY
      Serial.printf("ERROR: DID NOT PUBLISH DETECTED DEVICES\n");
      flashLED(strip.Color(255, 0, 0), 15000); // Flash red for error
    }
    
    if (!client.publish("homeassistant/sensor/mB/fmstatus/config", jsonFeedModeStatusDiscovery)) { // This is for the feed mode status
      Serial.printf("ERROR: DID NOT PUBLISH FM STATUS\n");
      flashLED(strip.Color(255, 0, 0), 15000); // Flash red for error
    }

    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: ");
    flashLED(strip.Color(0, 0, 255), 100); // Flash blue for in-progress

    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) && (currState)) {
              // Scene is different from feed mode (1), and Feed switch is ON, set device to feed mode
              if (!device.setFeedScene()) {
                client.publish("homeassistant/sensor/mB/fmstatus", "FM ERROR");
                Serial.println("FM Status: ERROR");
              }
            } else if ((sceneId == 1) && !currState) {
              // Scene is feed mode (1), and Feed switch is OFF, set device to Normal Schedule
              if (!device.runSchedule()) {
                client.publish("homeassistant/sensor/mB/fmstatus", "FM ERROR");
                Serial.println("FM Status: ERROR");
              }
            }

            // 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");
          flashLED(strip.Color(255, 0, 0), 15000); // Flash red for error
          client.publish("homeassistant/sensor/mB/fmstatus", "FM ERROR");
          Serial.println("FM Status: ERROR");
        } else {
          if (currState) {
            client.publish("homeassistant/sensor/mB/fmstatus", "FM ON OK");
            Serial.println("FM Status: FM ON OK");
          } else {
            client.publish("homeassistant/sensor/mB/fmstatus", "FM OFF OK");
            Serial.println("FM Status: FM OFF OK");
          }
        }
      }
    }

    char cstr[20];
    JsonDocument jsonQtyDev;
    jsonQtyDev["qtydevices"] = deviceCount;
    serializeJson(jsonQtyDev, cstr);

    Serial.printf("INFO: MOBIUS BLE DEVICE COUNT: %i\n", deviceCount);
    flashLED(strip.Color(0, 255, 0), 5000); // Flash green for success

    if (!client.publish("homeassistant/sensor/mB/state", cstr)) {
      Serial.printf("ERROR: DID NOT PUBLISH DETECTED DEVICES\n");
      flashLED(strip.Color(255, 0, 0), 15000); // Flash red for error
    }

    prevState = currState;
  }

  firstRun = false;
}
 

iamdan

Community Member
View Badges
Joined
Jul 1, 2022
Messages
67
Reaction score
63
Location
Western Australia
Rating - 0%
0   0   0
Does anyone know if possible and if so what to code:
-- Have a permanent (if toggled on) "Feed Mode" where the pumps are idling like feed mode or even not spinning but the main unit is still on so you can send commands to it? until you turn that mode off?

-- Is it possible to set feed mode longer than 10 minutes? either by the Mobius app so that this Feed Mode code will activate that or by programming in this code directly?

Reason being is i have some slow eating plecos in a rapids simulated env where i need to have the pumps idling for a period of time so they can get to their food :p
 

WHITE BUCKET CHALLENGE : How CLEAR do you think your water is in your reef aquarium? Show us your water!

  • Crystal Clear

    Votes: 63 39.9%
  • Mostly clear with a tint of yellow

    Votes: 81 51.3%
  • More yellow than clear

    Votes: 6 3.8%
  • YUCKY YELLOW

    Votes: 2 1.3%
  • Other (please explain)

    Votes: 6 3.8%
Back
Top