BruControl: Adding unsupported devices

Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum

Help Support Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

crane

Supporting Member
HBT Supporter
Joined
Sep 20, 2011
Messages
1,215
Reaction score
457
Location
San Diego
I wrote an Arduino sketch for the nodeMCU that can be used to enable unsupported interfaces/devices in BruControl. Hopefully other people out there can make some use of it as well.

Currently BruControl does not offer generic support for digital communication standards like UART, I2C, SPI, or 1-wire. For the latter 3 BruControl does support these interfaces, but only for a single device per bus standard (I2C = LCD display, SPI = RTC amplifier, 1-wire = temp sensor). Enabling generic support for any device that uses one of these 4 communication interfaces will not be a trivial task. For example, some UART devices will send out status information at a fixed time interval, whereas other devices require you to send a command to read a value. I2C gets more complicated, as most devices will allow you to read from the device with a single read command. Other devices require you to write an address value to a "read address" register before reading the value from a different register. On top of that there are multiple different ways to read back more than 8 bits from an I2C device.

The framework will communicate to BruControl over WiFi through BruControl's HTTP data exchange interface to read and write global values in BruControl. The user can add their own code in the framework to act upon global values and send back status to BruControl. This does require the user to be able to write their own Arduino sketch to interface with whatever device they are enabling support for. In fact, I would start by writing a sketch to interface with the unsupported device using the serial interface on the nodeMCU before integrating your code into this framework. I tried to add as many comments to make it self explanatory as to what and where you need to add your own code.

Disclaimer: There are probably better/more efficient ways to write this code and limited testing has been done on this framework.

This was written on version 1.8.10 of the Arduino IDE. Note, the nodeMCU is not supported in the Arduino IDE by default. You can find instructions for that here.

https://www.instructables.com/id/Quick-Start-to-Nodemcu-ESP8266-on-Arduino-IDE/

Code:
/**********************************************************************************
* BruControl nodeMCU http bridge
* Version: 0.2
*
* This framework provides a bridge between a nodeMCU and BruControl using BruControl's
* http GET/PUT data exchange protocol.
*   Basic flow
*     1. Every checkInterval each BruControl global variable in the globalsToRead array is read
*        and its value is placed in the corresonding index in the globalReadValues array.
*     2. Every calcInterval user defined code is ran to:
*           process inputs
*           interface with devices
*           calculate return values
*     3. Every sendInterval each BruControl global variable in the globalsToWrite array's
*        corresponding value in the globalValuesToWrite array is sent back to BruControl.
*
* General use of this framework.
*     Place your user code within the @@@@@@@@@@@ sections
*     There should be no need to modify the code outside of these sections.
*
************************************************************************************/

 
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Place User comments aboout your application here.
*
* 
*
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>


/**********************************************************************************
* BruControl Settings
*
* Modify the following code for the number of globals you want to read and update
* from/to BruControl, with they names of each global as it is named in BruControl.
*
* Set the server IP address and port as needed.
*
***********************************************************************************/
// The following are used to define what global variables in BruControl to monitor and update.
#define READSIZE 3  // Number of global variables to read
#define WRITESIZE 2  // Number of global variables to update
// Optional to define indices for variables to make it easier to use them
// Read Array Indices
#define GR1INDEX 0
#define GR2INDEX 1
#define GR3INDEX 2
// Write Array Indices
#define GW1INDEX 0
#define GW2INDEX 1
// Create arrays
String globalsToRead[READSIZE] = { "readGlobal1", "readGlobal2", "readGlobal3" }; // List of global variables to read as they are named in BruControl
String globalReadValues[READSIZE]; // Array to store read values in
String globalsToWrite[WRITESIZE] = { "writeGlobal1", "writeGlobal2" }; // List of global variables to update as they are named in BruControl
String globalValuesToWrite[WRITESIZE]; // Array to store write values in

// BruControl Server settings
char serverAddress[] = "192.192.192.192"; // BruControl Server IP Address
int port = 8000; // BruControl Server port

// Scheduling interval
unsigned long int delayInterval = 1000;  // milliseconds between each time the main loop runs
/**********************************************************************************
* End BruControl Settings
***********************************************************************************/

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Place user defined initialization code below
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

// Put your definitions here

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End User defined/modifiable variables
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


String readString; //String loaded with results from HTTP get requests
char temp_string[300]; // temp string used for sprintf's and other crap
ESP8266WiFiMulti WiFiMulti;

void setup() {
  Serial.begin(115200);
  Serial.println();
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("SSID", "PASSWORD"); //Change this to your Wifi settings
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP().toString());

  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user defined setup code below
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

 
  // Place your setup code here
 
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user defined setup code
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  delay(5000);
}


/**********************************************************************************
*  Main Loop to get inputs from BruControl, process them, calculate outputs,
*  and send updates back to BruControl
*
*  This allows you to use global variables in BruControl to interface with
*  unsupported devices.
*
*  In this case we are doing the following:
*     Polling BruControl for HopsBossLocation updates
*       HopsBossLocation is an integer from 0-7, 0 being home or closed, 1-7 corresponding
*       to motor shell locations.
*     Monitoring Serial port output of Hops-Boss for changes in:
*       Current Posittion
*       Currently Moving
*     Send command to Hops-Boss to move to new position if:
*       HopsBossLocation does not equal current location
*       and we are not currently moving
*     Upon stopping moving check to make sure:
*       Current Position is the same as HopsBossLocation
*     Send HopsBossmoving status back to BruControl
*   
***********************************************************************************/
void loop() {
  Serial.println("### Starting Main Loop ###################################################");
  Serial.println("  ## Starting to read variables from BruControl #####");
  getGlobals(); // get updates from BruControl
  Serial.println("  ## Done reading variables from BruControl #####");
  Serial.println("  @@ Starting to Parse and Caculate user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U@@@@@@@@@@@@");
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user function calls here
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

 
 
  // process inputs, interface with devices, and calculate return values every calcInterval

 
 
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user function calls
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  Serial.println("  @@ Done with user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  Serial.println("  ## Starting to write outputs back to BruControl #####");
  sendGlobals();  // send updates to BruControl
  Serial.println("  ## Done writing outputs to BruControl #####");
  delay(delayInterval);  // set delayInterval to how long you want to wait between executing the main loop
}
/**********************************************************************************
*  End Main Loop
***********************************************************************************/


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  Place user defined functions below for processing inputs, interfacing with
*  devices, and calculating return values.
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/



// Place your user functions here



/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End user defined functions
*
*  Start of framework functions
*    Don't modify the code below here!!!!
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


/**********************************************************************************
* getGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to get current values.
*
* This function will read all global variables in the globalsToRead array
* and fill the globalReadValues arrays with their current values.
*
* Do not modify this function. Instead set the following at the top of this file:
*   READSIZE - number of global variables to update
*   globalsToRead - names of global variables as they are named in BruControl
*   globalReadValues - Values for each global variable
*
***********************************************************************************/
void getGlobals() {
  int i;
  for(i=0; i<READSIZE; i++) {
    globalReadValues = getVariableValue(globalsToRead);
    Serial.print("     readString Is: ");
    Serial.print(globalsToRead);
    Serial.print(", ");
    Serial.println(globalReadValues);
  }
}


/**********************************************************************************
* sendGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to send updates to.
*
* This function will send all global variables in the globalsToWrite array with
* corresponding values from the globalValuesToWrite array.
*
* Do not modify this function. Instead set the following at the top of this file:
*   WRITESIZE - number of global variables to update
*   globalsToWrite - names of global variables as they are named in BruControl
*   globalValuestoWrite - Values for each global variable
*
***********************************************************************************/
void sendGlobals() {
  int i;
  for(i=0; i<WRITESIZE; i++) {
    sendVariableValue(globalsToWrite, globalValuesToWrite);
    Serial.print("     Write: ");
    Serial.print(globalsToWrite);
    Serial.print(", ");
    Serial.println(globalValuesToWrite);
  }
}


/**********************************************************************************
* getVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*
* Framework function to get values of individual BruControl global variables.
* This function is called by the getGlobals() framework function.
* The user should not call this function directly
*
* returns value of global variable in String form
*
***********************************************************************************/
String getVariableValue(String globalVariable) {
  String payload = "";
  StaticJsonDocument<512> jsonDoc;
  char temp1[100];
  char temp2[100];
 
  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;
  
    globalVariable.toCharArray(temp1,100);
    sprintf(temp2, "/global/%s", temp1);
    if (http.begin(client, serverAddress, port, temp2)) {
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  } 
  payload.toCharArray(temp1,300);
  DeserializationError error = deserializeJson(jsonDoc, temp1);
  if(error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return "";
  }
  const char* returnValue = jsonDoc["Value"];
  return returnValue;
}


/**********************************************************************************
* sendVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*   variableValue - value of variable in string form to send back to BruControl.
*
* Framework function to send updates to individual BruControl global variables.
* This function is called by the sendGlobals() framework function.
* The user should not call this function directly
*
***********************************************************************************/
void sendVariableValue(String globalVariable, String variableValue) {
  char temp1[100];
  char temp2[100];
  char temp3[100];
 
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;

    globalVariable.toCharArray(temp1,100);
    variableValue.toCharArray(temp2,100);
    sprintf(temp3, "[{\"Name\":\"%s\",\"Value\":\"%s\"}]", temp1, temp2);
    String jsonToWrite = temp3;

    if (http.begin(client, serverAddress, port, "/globals")) {  // HTTP
      http.addHeader("Content-Type", "application/json");
      http.addHeader("Content-Length", String(jsonToWrite.length()));
      // start connection and send HTTP header
      int httpCode = http.PUT(jsonToWrite);
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] PUT... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
}
 
Last edited:
Here is an example of an application using this framework to enable the hops-boss with BruControl.

Code:
/**********************************************************************************
* BruControl nodeMCU http bridge
* Version: 0.2
*
* This framework provides a bridge between a nodeMCU and BruControl using BruControl's
* http GET/PUT data exchange protocol.
*   Basic flow
*     1. Every checkInterval each BruControl global variable in the globalsToRead array is read
*        and its value is placed in the corresonding index in the globalReadValues array.
*     2. Every calcInterval user defined code is ran to:
*           process inputs
*           interface with devices
*           calculate return values
*     3. Every sendInterval each BruControl global variable in the globalsToWrite array's
*        corresponding value in the globalValuesToWrite array is sent back to BruControl.
*
************************************************************************************/

 
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Hops Boss UART Interface
*
* Polling BruControl for HopsBossLocation updates
*   HopsBossLocation is an integer from 0-7, 0 being home or closed, 1-7 corresponding
*   to motor shell locations.
* Monitoring Serial port output of Hops-Boss for changes in:
*   Current Position
* Process input, send updates to Hops Boss and calculate return value
* Send HopsBossmoving status back to BruControl
*
* Hops-Boss Interface is 5V TTL UART with 9V Power
* Baud Rate: 9600
* send "01<CRLF>" to get current position 0-7 where 0 is home.
*   Response will be *,x,0   where X is current position
* send "05X<CRLF>" to set the desired location, where X is 0-7, 0 being home
* <CRLF> is standard carriage return and linefeed ascii characters (ASCII 13 & ASCII 10 decimal ) to terminate line
* Hop Boss with automatically home upon start up.
*
* BruControl Data Exhange Interface uses HTTP send/get
* Global variables are formatted in json strings
*    HopsBossLocation is an integer 0-7 - read only
*    HopsBossMoving is a boolean send back to BC to indicate when the motor is moving
*
* RJ45 Pinout
*  Pin. Signal - T-568B Color coding
*   1. Vin (9V) - Orange/White
*   2. Vin (9V) - Orange
*   3. Vin (9V) - Green/White
*   4. Tx (5V IO) - Blue
*   5. Rx (5V IO) - Blue/White
*   6. GND - Green
*   7. GND - Brown/White
*   8. GND - Brown
*
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>


/**********************************************************************************
* BruControl Settings
*
* Modify the following code for the number of globals you want to read and update
* from/to BruControl, with they names of each global as it is named in BruControl.
*
* Set the server IP address and port as needed.
*
***********************************************************************************/
// The following are used to define what global variables in BruControl to monitor and update.
#define READSIZE 1  // Number of global variables to read
#define WRITESIZE 1  // Number of global variables to update
// Optional to define indices for variables to make it easier to use them
// Read Array Indices
#define HBPOSINDEX 0
// Write Array Indices
#define HBMOVINDEX 0
// Create arrays
String globalsToRead[READSIZE] = { "HopsBossPosition" }; // List of global variables to read as they are named in BruControl
String globalReadValues[READSIZE];
String globalsToWrite[WRITESIZE] = { "HopsBossMoving" }; // List of global variables to update as they are named in BruControl
String globalValuesToWrite[WRITESIZE];

// BruControl Server settings
char serverAddress[] = "10."; // BruControl Server IP Address
int port = 8000; // BruControl Server port

// Scheduling interval
unsigned long int delayInterval = 1000;  // milliseconds between each time the main loop runs
/**********************************************************************************
* End BruControl global definitions
***********************************************************************************/

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Place user defined initialization code below
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
#include <SoftwareSerial.h>
int currentPosition;
int lastPosition = -1;
int targetPosition;
boolean moving = false;

#define D5 (14) //Rx
#define D6 (12) //Tx
#define BAUD_RATE 9600

SoftwareSerial hopsSerial;
String inputStr = "";
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End User defined/modifiable variables
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


String readString; //String loaded with results from HTTP get requests
char temp_string[300]; // temp string used for sprintf's and other crap
ESP8266WiFiMulti WiFiMulti;

void setup() {
  Serial.begin(115200);
  Serial.println();
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("", "");
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP().toString());

  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user defined setup code below
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

 
  // Open serial communications for Hops Boss
  hopsSerial.begin(BAUD_RATE, SWSERIAL_8N1, D5, D6); //Rx, Tx
  Serial.println("Hops-Boss BruControl Data Exhange Bridge");
  delay(1000);
  readHopBoss(); // read initial startup garbage
  updateHopBoss(0); // sending position 0 command ensures proper homing of the hop boss
  moving = true;
 
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user defined setup code
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  delay(5000);
}


/**********************************************************************************
*  Main Loop to get inputs from BruControl, process them, calculate outputs,
*  and send updates back to BruControl
*
*  This allows you to use global variables in BruControl to interface with
*  unsupported devices.
*
*  In this case we are doing the following:
*     Polling BruControl for HopsBossLocation updates
*       HopsBossLocation is an integer from 0-7, 0 being home or closed, 1-7 corresponding
*       to motor shell locations.
*     Monitoring Serial port output of Hops-Boss for changes in:
*       Current Posittion
*       Currently Moving
*     Send command to Hops-Boss to move to new position if:
*       HopsBossLocation does not equal current location
*       and we are not currently moving
*     Upon stopping moving check to make sure:
*       Current Position is the same as HopsBossLocation
*     Send HopsBossmoving status back to BruControl
*    
***********************************************************************************/
void loop() {
  Serial.println("### Starting Main Loop ###################################################");
  Serial.println("  ## Starting to read variables from BruControl #####");
  getGlobals(); // get updates from BruControl
  Serial.println("  ## Done reading variables from BruControl #####");
  Serial.println("  @@ Starting to Parse and Caculate user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U@@@@@@@@@@@@");
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user function calls here
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

  // process inputs, interface with devices, and calculate return values every calcInterval

  readHopBoss();
  globalValuesToWrite[HBMOVINDEX] = updateHopBoss(globalReadValues[HBPOSINDEX].toInt());

  lastPosition = currentPosition; // update previous position to see if we have stopped homing

 
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user function calls
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  Serial.println("  @@ Done with user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  Serial.println("  ## Starting to write outputs back to BruControl #####");
  sendGlobals();  // send updates to BruControl
  Serial.println("  ## Done writing outputs to BruControl #####");
  delay(delayInterval);  // set delayInterval to how long you want to wait between executing the main loop
}
/**********************************************************************************
*  End Main Loop
***********************************************************************************/


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  Place user defined functions below for processing inputs, interfacing with
*  devices, and calculating return values.
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


/**********************************************************************************
* updateHopBoss()
*   BcPosition - current desired position from BruControl
*  
* Main state machine function for Hops Boss logic.
*   If the hops boss is homing do not send any updates until it is done homing.
*     Sending commands while homing will interrupt the homing process.
*     Upon ending homing tell the Hops Boss to move to the BcPosition, regardless.
*   If idle, check the following conditions before sending a commend to move:
*     not moving
*     not homing
*     valid BcPosition value
*     currentPosition does not equal BcPosition
*   If moving, check the following conditions to return to idle state:
*     currentPosition equals targetPosition
*  
* returns string to indicate if the Hops Boss is curretly moving or not
*  
***********************************************************************************/
String updateHopBoss(int BcPosition) {
  Serial.print("     UpdateHopBoss args: BcPosition = ");
  Serial.print(BcPosition);
  Serial.print(", moving = ");
  Serial.println(moving);

  if(currentPosition >= 0) { // Do nothing if we are homing
    // Check if homing just completed and send it to the current Bru Control Position
    if(currentPosition == 0 && lastPosition == -1) sendHopBoss(BcPosition);
 
    if(!moving) {
      Serial.println("       We are currently not moving");
      if(BcPosition >= 0 && BcPosition <= 7) {
        Serial.println("         BcPosition is a valid position (0-7)");
        if(currentPosition != BcPosition) {
          Serial.print("           Current Position: ");
          Serial.print(currentPosition);
          Serial.print(", does not equal BcPosition: ");
          Serial.println(BcPosition);
          // Send command to move to BcPosition
          sendHopBoss(BcPosition);
        }
      }
    } else { // Check if we are done moving
      Serial.print("        Checking if current_position: ");
      Serial.print(currentPosition);
      Serial.print(", is at the targetPosition: ");
      Serial.println(targetPosition);
      if(currentPosition == targetPosition) {
        Serial.println("        We are done moving");
        moving = false;
      }
    }
  } else {
    moving = true;
  }
  if(moving) {
    return "true";
  } else {
    return "false";
  }
}


/**********************************************************************************
* sendHopBoss()
*   BcPosition - current desired position from BruControl to send to the Hops Boss
*     needs to be (0-7)
*     This function is called by updateHopBoss() only.
*
* Sends command over uart to Hops Boss to move to new position: BcPosition.
*
***********************************************************************************/
void sendHopBoss(int BcPosition) {
  Serial.print("            Moving to position: ");
  Serial.println(BcPosition);
  moving = true;
  targetPosition = BcPosition;
  char temp1[100];
  sprintf(temp1, "05%d", BcPosition);
  hopsSerial.println(temp1);
}


/**********************************************************************************
* readHopBoss()
*
* reads the currenct position from the Hops Boss
*
***********************************************************************************/
void readHopBoss() {
  int i = 0;
  char rc;
  char inputChArray[32];
 
  while (hopsSerial.available() > 0) {
    rc = hopsSerial.read();
    if(rc != '\n' && rc != '\r') {
      inputChArray[i] = rc;
      i++;
      yield();
    } else {
      inputChArray[i] = '\0';
    }
  }
  inputStr = inputChArray;
  currentPosition = getValue(inputChArray, ',', 1).toInt();
  Serial.print("     Finished reading from HopsBoss, Current Position: ");
  Serial.println(currentPosition);
}


/**********************************************************************************
* getValues()
*   data - string to split
*   seperator - deliminator to split string on
*   index - index of substring to return
*
* finds the substring at the specifiec index using separator as a delimintor.
*  
* returns substring of item at index
*  
***********************************************************************************/
String getValue(String data, char separator, int index) {
  int maxIndex = data.length() - 1;
  int j = 0;
  String chunkVal = "";

  for (int i = 0; i <= maxIndex && j <= index; i++) {
    chunkVal.concat(data[i]);
    if (data[i] == separator) {
      j++;
      if (j > index) {
        chunkVal.trim();
        return chunkVal;
      }
      chunkVal = "";
    } else if ((i == maxIndex) && (j < index)) {
      chunkVal = "";
      return chunkVal;
    }
  }  
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End user defined functions
*
*  Start of framework functions
*    Don't modify the code below here!!!!
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


/**********************************************************************************
* getGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to get current values.
*
* This function will read all global variables in the globalsToRead array
* and fill the globalReadValues arrays with their current values.
*
* Do not modify this function. Instead set the following at the top of this file:
*   READSIZE - number of global variables to update
*   globalsToRead - names of global variables as they are named in BruControl
*   globalReadValues - Values for each global variable
*
***********************************************************************************/
void getGlobals() {
  int i;
  for(i=0; i<READSIZE; i++) {
    globalReadValues[i] = getVariableValue(globalsToRead[i]);
    Serial.print("     readString Is: ");
    Serial.print(globalsToRead[i]);
    Serial.print(", ");
    Serial.println(globalReadValues[i]);
  }
}


/**********************************************************************************
* sendGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to send updates to.
*
* This function will send all global variables in the globalsToWrite array with
* corresponding values from the globalValuesToWrite array.
*
* Do not modify this function. Instead set the following at the top of this file:
*   WRITESIZE - number of global variables to update
*   globalsToWrite - names of global variables as they are named in BruControl
*   globalValuestoWrite - Values for each global variable
*
***********************************************************************************/
void sendGlobals() {
  int i;
  for(i=0; i<WRITESIZE; i++) {
    sendVariableValue(globalsToWrite[i], globalValuesToWrite[i]);
    Serial.print("     Write: ");
    Serial.print(globalsToWrite[i]);
    Serial.print(", ");
    Serial.println(globalValuesToWrite[i]);
  }
}


/**********************************************************************************
* getVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*
* Framework function to get values of individual BruControl global variables.
* This function is called by the getGlobals() framework function.
* The user should not call this function directly
*
* returns value of global variable in String form
*
***********************************************************************************/
String getVariableValue(String globalVariable) {
  String payload = "";
  StaticJsonDocument<512> jsonDoc;
  char temp1[100];
  char temp2[100];
 
  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;
   
    globalVariable.toCharArray(temp1,100);
    sprintf(temp2, "/global/%s", temp1);
    if (http.begin(client, serverAddress, port, temp2)) {
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }  
  payload.toCharArray(temp1,300);
  DeserializationError error = deserializeJson(jsonDoc, temp1);
  if(error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return "";
  }
  const char* returnValue = jsonDoc["Value"];
  return returnValue;
}


/**********************************************************************************
* sendVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*   variableValue - value of variable in string form to send back to BruControl.
*
* Framework function to send updates to individual BruControl global variables.
* This function is called by the sendGlobals() framework function.
* The user should not call this function directly
*
***********************************************************************************/
void sendVariableValue(String globalVariable, String variableValue) {
  char temp1[100];
  char temp2[100];
  char temp3[100];
 
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;

    globalVariable.toCharArray(temp1,100);
    variableValue.toCharArray(temp2,100);
    sprintf(temp3, "[{\"Name\":\"%s\",\"Value\":\"%s\"}]", temp1, temp2);
    String jsonToWrite = temp3;

    if (http.begin(client, serverAddress, port, "/globals")) {  // HTTP
      http.addHeader("Content-Type", "application/json");
      http.addHeader("Content-Length", String(jsonToWrite.length()));
      // start connection and send HTTP header
      int httpCode = http.PUT(jsonToWrite);
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] PUT... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
}

These are the global values that this application interfaces with. The position number is read from BruControl. The application will send back status of whether it is currently moving or not.

BcHopBoss.PNG


BcHopBoss2.PNG


Finally, here is some serial output from the nodeMCU while I was testing this.

serialLog.PNG
 
Last edited:
Hmm...I currently use arduinos to read load cells and then output a 0-5 VDC signal to send to BC. Would this be able to eliminate the need to output 0-5 VDC and just send the digital value from the arduino running the load cells to bru control?

Thanks,
p.d.
 
IMG_5277.JPG


I’m using your Arduino sketch for a HopsBoss. I get this error message. Am I right that the line is missing two things: an end quote and a close parentheses. Where should they go, if so?

Before the bracket at the end of the line is my thought.
 
Am I going crazy? I appears that the "code" sections are omitting some of the code.

Here is what I see in the final post.

upload_2020-3-15_9-0-32.png



When I go to edit my post the code is correct. Awww. WTF.

upload_2020-3-15_9-1-25.png


Anyways, the last screenshot has the correct syntax for the code.
 

Attachments

  • upload_2020-3-15_8-57-20.png
    upload_2020-3-15_8-57-20.png
    64.7 KB · Views: 23
  • upload_2020-3-15_8-58-7.png
    upload_2020-3-15_8-58-7.png
    13 KB · Views: 22
Code:
/**********************************************************************************
* BruControl nodeMCU http bridge
* Version: Poopy.2
*
* This framework provides a bridge between a nodeMCU and BruControl using BruControl's
* http GET/PUT data exchange protocol.
*   Basic flow
*     1. Every checkInterval each BruControl global variable in the globalsToRead array is read
*        and its value is placed in the corresonding index in the globalReadValues array.
*     2. Every calcInterval user defined code is ran to:
*           process inputs
*           interface with devices
*           calculate return values
*     3. Every sendInterval each BruControl global variable in the globalsToWrite array's
*        corresponding value in the globalValuesToWrite array is sent back to BruControl.
*
************************************************************************************/


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Hops Boss UART Interface
*
* Polling BruControl for HopsBossLocation updates
*   HopsBossLocation is an integer from 0-7, 0 being home or closed, 1-7 corresponding
*   to motor shell locations.
* Monitoring Serial port output of Hops-Boss for changes in:
*   Current Position
* Process input, send updates to Hops Boss and calculate return value
* Send HopsBossmoving status back to BruControl
*
* Hops-Boss Interface is 5V TTL UART with 9V Power
* Baud Rate: 9600
* send "01<CRLF>" to get current position 0-7 where 0 is home.
*   Response will be *,x,0   where X is current position
* send "05X<CRLF>" to set the desired location, where X is 0-7, 0 being home
* <CRLF> is standard carriage return and linefeed ascii characters (ASCII 13 & ASCII 10 decimal ) to terminate line
* Hop Boss with automatically home upon start up.
*
* BruControl Data Exhange Interface uses HTTP send/get
* Global variables are formatted in json strings
*    HopsBossLocation is an integer 0-7 - read only
*    HopsBossMoving is a boolean send back to BC to indicate when the motor is moving
*
* RJ45 Pinout
*  Pin. Signal - T-568B Color coding
*   1. Vin (9V) - Orange/White
*   2. Vin (9V) - Orange
*   3. Vin (9V) - Green/White
*   4. Tx (5V IO) - Blue
*   5. Rx (5V IO) - Blue/White
*   6. GND - Green
*   7. GND - Brown/White
*   8. GND - Brown
*
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>


/**********************************************************************************
* BruControl Settings
*
* Modify the following code for the number of globals you want to read and update
* from/to BruControl, with they names of each global as it is named in BruControl.
*
* Set the server IP address and port as needed.
*
***********************************************************************************/
// The following are used to define what global variables in BruControl to monitor and update.
#define READSIZE 1  // Number of global variables to read
#define WRITESIZE 1  // Number of global variables to update
// Optional to define indices for variables to make it easier to use them
// Read Array Indices
#define HBPOSINDEX 0
// Write Array Indices
#define HBMOVINDEX 0
// Create arrays
String globalsToRead[READSIZE] = { "HopsBossPosition" }; // List of global variables to read as they are named in BruControl
String globalReadValues[READSIZE];
String globalsToWrite[WRITESIZE] = { "HopsBossMoving" }; // List of global variables to update as they are named in BruControl
String globalValuesToWrite[WRITESIZE];

// BruControl Server settings
char serverAddress[] = "111.222.333.444"; // BruControl Server IP Address
int port = 8000; // BruControl Server port

// Scheduling interval
unsigned long int delayInterval = 1000;  // milliseconds between each time the main loop runs
/**********************************************************************************
* End BruControl global definitions
***********************************************************************************/

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Place user defined initialization code below
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
#include <SoftwareSerial.h>
int currentPosition;
int lastPosition = -1;
int targetPosition;
boolean moving = false;

#define D5 (14) //Rx
#define D6 (12) //Tx
#define BAUD_RATE 9600

SoftwareSerial hopsSerial;
String inputStr = "";
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End User defined/modifiable variables
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


String readString; //String loaded with results from HTTP get requests
char temp_string[300]; // temp string used for sprintf's and other crap
ESP8266WiFiMulti WiFiMulti;

void setup() {
  Serial.begin(115200);
  Serial.println();
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("SSID", "pass");
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP().toString());

  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user defined setup code below
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

 
  // Open serial communications for Hops Boss
  hopsSerial.begin(BAUD_RATE, SWSERIAL_8N1, D5, D6); //Rx, Tx
  Serial.println("Hops-Boss BruControl Data Exhange Bridge");
  delay(1000);
  readHopBoss(); // read initial startup garbage
  updateHopBoss(0); // sending position 0 command ensures proper homing of the hop boss
  moving = true;
 
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user defined setup code
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  delay(5000);
}


/**********************************************************************************
*  Main Loop to get inputs from BruControl, process them, calculate outputs,
*  and send updates back to BruControl
*
*  This allows you to use global variables in BruControl to interface with
*  unsupported devices.
*
*  In this case we are doing the following:
*     Polling BruControl for HopsBossLocation updates
*       HopsBossLocation is an integer from 0-7, 0 being home or closed, 1-7 corresponding
*       to motor shell locations.
*     Monitoring Serial port output of Hops-Boss for changes in:
*       Current Posittion
*       Currently Moving
*     Send command to Hops-Boss to move to new position if:
*       HopsBossLocation does not equal current location
*       and we are not currently moving
*     Upon stopping moving check to make sure:
*       Current Position is the same as HopsBossLocation
*     Send HopsBossmoving status back to BruControl
*
***********************************************************************************/
void loop() {
  Serial.println("### Starting Main Loop ###################################################");
  Serial.println("  ## Starting to read variables from BruControl #####");
  getGlobals(); // get updates from BruControl
  Serial.println("  ## Done reading variables from BruControl #####");
  Serial.println("  @@ Starting to Parse and Caculate user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U@@@@@@@@@@@@");
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user function calls here
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

  // process inputs, interface with devices, and calculate return values every calcInterval

  readHopBoss();
  globalValuesToWrite[HBMOVINDEX] = updateHopBoss(globalReadValues[HBPOSINDEX].toInt());

  lastPosition = currentPosition; // update previous position to see if we have stopped homing

 
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user function calls
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  Serial.println("  @@ Done with user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  Serial.println("  ## Starting to write outputs back to BruControl #####");
  sendGlobals();  // send updates to BruControl
  Serial.println("  ## Done writing outputs to BruControl #####");
  delay(delayInterval);  // set delayInterval to how long you want to wait between executing the main loop
}
/**********************************************************************************
*  End Main Loop
***********************************************************************************/


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  Place user defined functions below for processing inputs, interfacing with
*  devices, and calculating return values.
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


/**********************************************************************************
* updateHopBoss()
*   BcPosition - current desired position from BruControl
*
* Main state machine function for Hops Boss logic.
*   If the hops boss is homing do not send any updates until it is done homing.
*     Sending commands while homing will interrupt the homing process.
*     Upon ending homing tell the Hops Boss to move to the BcPosition, regardless.
*   If idle, check the following conditions before sending a commend to move:
*     not moving
*     not homing
*     valid BcPosition value
*     currentPosition does not equal BcPosition
*   If moving, check the following conditions to return to idle state:
*     currentPosition equals targetPosition
*
* returns string to indicate if the Hops Boss is curretly moving or not
*
***********************************************************************************/
String updateHopBoss(int BcPosition) {
  Serial.print("     UpdateHopBoss args: BcPosition = ");
  Serial.print(BcPosition);
  Serial.print(", moving = ");
  Serial.println(moving);

  if(currentPosition >= 0) { // Do nothing if we are homing
    // Check if homing just completed and send it to the current Bru Control Position
    if(currentPosition == 0 && lastPosition == -1) sendHopBoss(BcPosition);
 
    if(!moving) {
      Serial.println("       We are currently not moving");
      if(BcPosition >= 0 && BcPosition <= 7) {
        Serial.println("         BcPosition is a valid position (0-7)");
        if(currentPosition != BcPosition) {
          Serial.print("           Current Position: ");
          Serial.print(currentPosition);
          Serial.print(", does not equal BcPosition: ");
          Serial.println(BcPosition);
          // Send command to move to BcPosition
          sendHopBoss(BcPosition);
        }
      }
    } else { // Check if we are done moving
      Serial.print("        Checking if current_position: ");
      Serial.print(currentPosition);
      Serial.print(", is at the targetPosition: ");
      Serial.println(targetPosition);
      if(currentPosition == targetPosition) {
        Serial.println("        We are done moving");
        moving = false;
      }
    }
  } else {
    moving = true;
  }
  if(moving) {
    return "true";
  } else {
    return "false";
  }
}


/**********************************************************************************
* sendHopBoss()
*   BcPosition - current desired position from BruControl to send to the Hops Boss
*     needs to be (0-7)
*     This function is called by updateHopBoss() only.
*
* Sends command over uart to Hops Boss to move to new position: BcPosition.
*
***********************************************************************************/
void sendHopBoss(int BcPosition) {
  Serial.print("            Moving to position: ");
  Serial.println(BcPosition);
  moving = true;
  targetPosition = BcPosition;
  char temp1[100];
  sprintf(temp1, "05%d", BcPosition);
  hopsSerial.println(temp1);
}


/**********************************************************************************
* readHopBoss()
*
* reads the currenct position from the Hops Boss
*
***********************************************************************************/
void readHopBoss() {
  int i = 0;
  char rc;
  char inputChArray[32];
 
  while (hopsSerial.available() > 0) {
    rc = hopsSerial.read();
    if(rc != '\n' && rc != '\r') {
      inputChArray = rc;
      i++;
      yield();
    } else {
      inputChArray = '\0';
    }
  }
  inputStr = inputChArray;
  currentPosition = getValue(inputChArray, ',', 1).toInt();
  Serial.print("     Finished reading from HopsBoss, Current Position: ");
  Serial.println(currentPosition);
}


/**********************************************************************************
* getValues()
*   data - string to split
*   seperator - deliminator to split string on
*   index - index of substring to return
*
* finds the substring at the specifiec index using separator as a delimintor.
*
* returns substring of item at index
*
***********************************************************************************/
String getValue(String data, char separator, int index) {
  int maxIndex = data.length() - 1;
  int j = 0;
  String chunkVal = "";

  for (int i = 0; i <= maxIndex && j <= index; i++) {
    chunkVal.concat(data);
    if (data == separator) {
      j++;
      if (j > index) {
        chunkVal.trim();
        return chunkVal;
      }
      chunkVal = "";
    } else if ((i == maxIndex) && (j < index)) {
      chunkVal = "";
      return chunkVal;
    }
  }
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End user defined functions
*
*  Start of framework functions
*    Don't modify the code below here!!!!
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


/**********************************************************************************
* getGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to get current values.
*
* This function will read all global variables in the globalsToRead array
* and fill the globalReadValues arrays with their current values.
*
* Do not modify this function. Instead set the following at the top of this file:
*   READSIZE - number of global variables to update
*   globalsToRead - names of global variables as they are named in BruControl
*   globalReadValues - Values for each global variable
*
***********************************************************************************/
void getGlobals() {
  int i;
  for(i=0; i<READSIZE; i++) {
    globalReadValues = getVariableValue(globalsToRead);
    Serial.print("     readString Is: ");
    Serial.print(globalsToRead);
    Serial.print(", ");
    Serial.println(globalReadValues);
  }
}


/**********************************************************************************
* sendGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to send updates to.
*
* This function will send all global variables in the globalsToWrite array with
* corresponding values from the globalValuesToWrite array.
*
* Do not modify this function. Instead set the following at the top of this file:
*   WRITESIZE - number of global variables to update
*   globalsToWrite - names of global variables as they are named in BruControl
*   globalValuestoWrite - Values for each global variable
*
***********************************************************************************/
void sendGlobals() {
  int i;
  for(i=0; i<WRITESIZE; i++) {
    sendVariableValue(globalsToWrite, globalValuesToWrite);
    Serial.print("     Write: ");
    Serial.print(globalsToWrite);
    Serial.print(", ");
    Serial.println(globalValuesToWrite);
  }
}


/**********************************************************************************
* getVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*
* Framework function to get values of individual BruControl global variables.
* This function is called by the getGlobals() framework function.
* The user should not call this function directly
*
* returns value of global variable in String form
*
***********************************************************************************/
String getVariableValue(String globalVariable) {
  String payload = "";
  StaticJsonDocument<512> jsonDoc;
  char temp1[100];
  char temp2[100];
 
  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;
 
    globalVariable.toCharArray(temp1,100);
    sprintf(temp2, "/global/%s", temp1);
    if (http.begin(client, serverAddress, port, temp2)) {
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
  payload.toCharArray(temp1,300);
  DeserializationError error = deserializeJson(jsonDoc, temp1);
  if(error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return "";
  }
  const char* returnValue = jsonDoc["Value"];
  return returnValue;
}


/**********************************************************************************
* sendVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*   variableValue - value of variable in string form to send back to BruControl.
*
* Framework function to send updates to individual BruControl global variables.
* This function is called by the sendGlobals() framework function.
* The user should not call this function directly
*
***********************************************************************************/
void sendVariableValue(String globalVariable, String variableValue) {
  char temp1[100];
  char temp2[100];
  char temp3[100];
 
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;

    globalVariable.toCharArray(temp1,100);
    variableValue.toCharArray(temp2,100);
    sprintf(temp3, "[{\"Name\":\"%s\",\"Value\":\"%s\"}]", temp1, temp2);
    String jsonToWrite = temp3;

    if (http.begin(client, serverAddress, port, "/globals")) {  // HTTP
      http.addHeader("Content-Type", "application/json");
      http.addHeader("Content-Length", String(jsonToWrite.length()));
      // start connection and send HTTP header
      int httpCode = http.PUT(jsonToWrite);
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] PUT... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
}

Edit: Interesting... I created a "quote" and pasted my code into it and save it. It showed everything except for the indentations. I edited the post and changed the "quote" header/footer to "code" and it looks to have all the indentations and all the code there. Silly nonsense these computers are.

Edit: Change the 2 original post's code sections to "QUOTE" and then back to "CODE" made the missing code come back, somehow...
 
Last edited:
@crane I’m finally in a place where I got your HopsBoss sketch running properly (network issues, COVID-19 delays, and my brewery is not at my home). Now I’m trouble shooting which wires go to which pins. From re-reading your Unsupported Brucontrol device thread and your personal build thread many many times, it looks like there are 3 wire connections plus the required +/- dc voltage connections. I have the later down. It’s the other connections that I wanted to confirm with you. Are these correct?

NodeMCU D5 (pin 14) to HopsBoss RX
NodeMCU D6 (pin 12) to HopsBoss TX
NodeMCU RX to HopsBoss TX with 1.1kohm resistor in series

Thanks.
 
This is pretty rad, I may use this in the future, and I'm sure @BrunDog is stoked to see more support to integrate Arduino into BruControl.

Any thoughts on packaging this into it's own object class and include as it's own library?
 
You brainiacs crack me up! I understood maybe half the words you use. I’m thankful you guys and gals can use your heads for something more than a hat rack. It is fun to sort of get a glimpse of how things work.
Carry on.
 
This is pretty rad, I may use this in the future, and I'm sure @BrunDog is stoked to see more support to integrate Arduino into BruControl.

Any thoughts on packaging this into it's own object class and include as it's own library?

This is a good point. I don't think I ever gave this idea and process its due... really nice work @crane!!
 
I'm glad other people can make use of this. In terms of packaging this into a library, that is a little beyond my reach in terms of skills and time. Mostly time these days. However, I did post this for others to use (and improve on) so maybe someone who has the time and knowhow can put in that legwork.
 
great work here @crane , @BrunDog has suggested that this method could be used to get ispindel to integrate directly with Brucontrol professional. complete noob here so any advice appreciated. Should i be trying to get create code to listen for a normal ispindel output to say mqtt from a second device or should new code as above be flashed onto the ispindel with inserted code to manage the normal ispindel operation? the ispindel firmware is packaged and huge so im unsure how to access it as an arduino sketch to even begin with.
 
The next device I am looking to add uses Bluetooth, so the esp8266 nodeMCU wont work. I modified the original code for the esp32.

To do so change the #include <> at the top as shown below, as well as the changes in the second screenshot above and inside the setup() function. Everything else remains the same.

esp8266-esp32_change1.PNG






esp8266-esp32_change2.PNG
 
Last edited:
I have been playing around with load cells and the HX711. Here is the code I came up with. It supports Taring, single point calibration, and switching units (g, oz, lbs, kg). It uses the onboard EEPROM to store the unit and calibration value so it's preserved during a power cycle. Even though the HX711 can be powered down to 2.7V, I was not able to get it to work at 3.3V from the nodeMCU. After a little googling I found out that the particular HX711 boards I have will only work at 5V. So for this I powered the HX711 off the Vin pin of the nodeMCU and used 1K:2K Ohm voltage divider to level shift the HX711 output from 5V to 3.3V.

C-like:
/**********************************************************************************
* BruControl Single load Cell nodeMCU http bridge
* Version: 0.2
*
* This framework provides a bridge between a nodeMCU and BruControl using BruControl's
* http GET/PUT data exchange protocol.
*   Basic flow
*     1. Every checkInterval each BruControl global variable in the globalsToRead array is read
*        and its value is placed in the corresonding index in the globalReadValues array.
*     2. Every calcInterval user defined code is ran to:
*           process inputs
*           interface with devices
*           calculate return values
*     3. Every sendInterval each BruControl global variable in the globalsToWrite array's
*        corresponding value in the globalValuesToWrite array is sent back to BruControl.
*
* General use of this framework.
*     Place your user code within the @@@@@@@@@@@ sections
*     There should be no need to modify the code outside of these sections.
*
************************************************************************************/


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Place User comments aboout your application here.
*
*  
*
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <EEPROM.h>
#include <HX711_ADC.h>
#include<stdlib.h>

/**********************************************************************************
* BruControl Settings
*
* Modify the following code for the number of globals you want to read and update
* from/to BruControl, with they names of each global as it is named in BruControl.
*
* Set the server IP address and port as needed.
*
***********************************************************************************/
// The following are used to define what global variables in BruControl to monitor and update.
#define READSIZE 4  // Number of global variables to read
#define WRITESIZE 3  // Number of global variables to update
// Optional to define indices for variables to make it easier to use them
// Read Array Indices
#define TARE 0
#define CALIBRATE 1
#define CALIBRATEVALUE 2
#define UNIT 3
// Write Array Indices
#define TARE 0
#define CALIBRATE 1
#define WEIGHT 2
// Create arrays
String globalsToRead[READSIZE] = { "TestScaleTare", "TestScaleCalibrate", "TestScaleCalibrateValue", "TestScaleUnit" }; // List of global variables to read as they are named in BruControl
String globalReadValues[READSIZE]; // Array to store read values in
String globalsToWrite[WRITESIZE] = { "TestScaleTare", "TestScaleCalibrate", "TestScaleWeight" }; // List of global variables to update as they are named in BruControl
String globalValuesToWrite[WRITESIZE]; // Array to store write values in

// BruControl Server settings
char serverAddress[] = "192.192.192.192"; // BruControl Server IP Address
int port = 8000; // BruControl Server port

// Scheduling interval
unsigned long int delayInterval = 100;  // milliseconds between each time the main loop runs
/**********************************************************************************
* End BruControl Settings
***********************************************************************************/

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
* Place user defined initialization code below
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

#define G 0
#define OZ 1
#define LBS 2
#define KG 3

// 2D array that contains conversion from each unit to an
float conversionTable[4][4] = {{1, 0.035274, 0.00220462, 0.001}, {28.3495, 1, 0.0625, 0.0283495}, {453.592, 16, 1, 0.453592}, {1000, 35.274, 2.20462, 1}};

// array to capture string values for the units
String units[4] = { "g", "oz", "lbs", "kg" };

int currentUnit = G;
float currentCalVal = 210.19;

//pins:
const int HX711_dout = 5; //mcu > HX711 dout pin
const int HX711_sck = 4; //mcu > HX711 sck pin

//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);


const int calVal_eepromAdress = 0;
const int unitVal_eepromAdress = 10;

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End User defined/modifiable variables
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


String readString; //String loaded with results from HTTP get requests
char temp_string[300]; // temp string used for sprintf's and other crap
ESP8266WiFiMulti WiFiMulti;

void setup() {
  Serial.begin(115200);
  Serial.println();
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("SSID", "PASSWORD"); //Change this to your Wifi settings
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(WiFi.localIP().toString());

  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user defined setup code below
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

  EEPROM.begin(512);
  LoadCell.begin();
  unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time

  LoadCell.start(stabilizingtime, true);
  if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
  } else {
    EEPROM.get(calVal_eepromAdress, currentCalVal);
    Serial.print("Calibration value read from EEPROM: ");
    Serial.println(currentCalVal);
    LoadCell.setCalFactor(currentCalVal); // user set calibration value (float), initial value 1.0 may be used for this sketch
    Serial.println("Startup is complete");
  }

  //currentCalVal = 210.19;
  //LoadCell.setCalFactor(currentCalVal);

  EEPROM.get(unitVal_eepromAdress, currentUnit);  // get last unit used

//  Serial.println("Writing out calibration conversion table");
//  for(int i=0; i<4; i++) {
//    for (int j=0; j<4; j++) {
//      Serial.print("Array Indices: ");
//      Serial.print(i);
//      Serial.print(", ");
//      Serial.println(j);
//      Serial.print("ConversionTable value: ");
//      Serial.println(conversionTable[i][j], 10);
//    }
//  }


  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user defined setup code
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  delay(5000);
}


/**********************************************************************************
*  Main Loop to get inputs from BruControl, process them, calculate outputs,
*  and send updates back to BruControl
*
*  This allows you to use global variables in BruControl to interface with
*  unsupported devices.
*
*  In this case we are doing the following:
*     Polling BruControl for HopsBossLocation updates
*       HopsBossLocation is an integer from 0-7, 0 being home or closed, 1-7 corresponding
*       to motor shell locations.
*     Monitoring Serial port output of Hops-Boss for changes in:
*       Current Posittion
*       Currently Moving
*     Send command to Hops-Boss to move to new position if:
*       HopsBossLocation does not equal current location
*       and we are not currently moving
*     Upon stopping moving check to make sure:
*       Current Position is the same as HopsBossLocation
*     Send HopsBossmoving status back to BruControl
*    
***********************************************************************************/
void loop() {
  Serial.println("### Starting Main Loop ###################################################");
  Serial.println("  ## Starting to read variables from BruControl #####");
  getGlobals(); // get updates from BruControl
  Serial.println("  ## Done reading variables from BruControl #####");
  Serial.println("  @@ Starting to Parse and Caculate user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@U@@@@@@@@@@@@");
  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * Place user function calls here
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

  String newUnitStr = globalReadValues[UNIT];
  int newUnit = currentUnit;
  if (newUnitStr == "g") {
    newUnit = G;
  } else if (newUnitStr == "oz") {
    newUnit = OZ;
  } else if (newUnitStr == "lbs") {
    newUnit = LBS;
  } else if (newUnitStr == "kg") {
    newUnit = KG;
  }


//  Serial.println(newUnit);
//  Serial.println(currentUnit);
  if(newUnit != currentUnit) {
    Serial.println("calling convertUnit");
    convertUnit(newUnit);
  }
   
  if(globalReadValues[TARE] == "True") {
    Serial.println("Calling Tare function");
    tareScale();
    globalValuesToWrite[TARE] = "False";
  } else if(globalReadValues[CALIBRATE] == "True") {
    Serial.println("Calling calibrate function");
    calibrateScale(globalReadValues[CALIBRATEVALUE]);
    globalValuesToWrite[CALIBRATE] = "False";
  }
  Serial.println("Reading Weight");
  String returnFloat = float2String(readWeight());
  globalValuesToWrite[WEIGHT] = returnFloat + " " + units[currentUnit];



  /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
  * End user function calls
  *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  Serial.println("  @@ Done with user code @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  Serial.println("  ## Starting to write outputs back to BruControl #####");
  sendGlobals();  // send updates to BruControl
  Serial.println("  ## Done writing outputs to BruControl #####");
  delay(delayInterval);  // set delayInterval to how long you want to wait between executing the main loop
}
/**********************************************************************************
*  End Main Loop
***********************************************************************************/


/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  Place user defined functions below for processing inputs, interfacing with
*  devices, and calculating return values.
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/

void convertUnit(int newUnitVal) {
  float newCalVal = currentCalVal / conversionTable[currentUnit][newUnitVal];
//  Serial.print("currentCalVal");
//  Serial.println(currentCalVal);
//  Serial.print("newUnitVal: ");
//  Serial.println(newUnitVal);
//  Serial.print("newCalVal: ");
//  Serial.println(newCalVal);
//  Serial.println(conversionTable[currentUnit][newUnitVal], 10);

  currentCalVal = newCalVal;
  currentUnit = newUnitVal;
  LoadCell.setCalFactor(currentCalVal);

  // write new unit value to EEPROM
  EEPROM.put(calVal_eepromAdress, newCalVal);
  EEPROM.put(unitVal_eepromAdress, newUnitVal);
  EEPROM.commit();
}

void tareScale() {
  Serial.println("updating loadCell");
  LoadCell.update();
  Serial.println("Calling tareNoDelay");
  LoadCell.tareNoDelay();

  Serial.println("Entering while loop");
  boolean _resume = false;
  while (_resume == false) {
    LoadCell.update();
    // check if last tare operation is complete
    if (LoadCell.getTareStatus() == true) {
      Serial.println("Tare complete");
      _resume = true;
    }
  }
}

void calibrateScale(String CalValue) {
  float known_mass = CalValue.toFloat();
  LoadCell.update();

  LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct
  float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value

  Serial.print("newCalibrationValue");
  Serial.println(newCalibrationValue, 10);
  // write new cal value to EEPROM
  EEPROM.put(calVal_eepromAdress, newCalibrationValue);
  EEPROM.commit();
}

float readWeight() {
  static boolean newDataReady = 0;
  float readWeight;
  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    readWeight = LoadCell.getData();
      Serial.print("Load_cell output val: ");
      Serial.println(readWeight);
      newDataReady = 0;
  }
  return readWeight;
}

//String readWeight() {
//  static boolean newDataReady = 0;
//  float readWeight;
//  // check for new data/start next conversion:
//  for(int i=0; i<100; i++) {
//    if (LoadCell.update()) newDataReady = true;
//
//    // get smoothed value from the dataset:
//    if (newDataReady) {
//      readWeight = LoadCell.getData();
//      newDataReady = 0;
//    }
//    delay(5);
//  }
//
//  return String(readWeight);
//}

String float2String(float numFloat) {
  int fl2Int = int(numFloat);
  Serial.print("Integer of float: ");
  Serial.println(fl2Int);
  int fl2Dec = round((numFloat * 10) - (fl2Int * 10) / 10);
  Serial.print("Decimal of float: ");
  Serial.println(fl2Dec);
  String returnStr = String(fl2Int) + "." + String(fl2Dec);
  Serial.print("float2Str return string: ");
  Serial.println(returnStr);
  return returnStr;
}

/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
*  End user defined functions
*
*  Start of framework functions
*    Don't modify the code below here!!!!
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/


/**********************************************************************************
* getGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to get current values.
*
* This function will read all global variables in the globalsToRead array
* and fill the globalReadValues arrays with their current values.
*
* Do not modify this function. Instead set the following at the top of this file:
*   READSIZE - number of global variables to update
*   globalsToRead - names of global variables as they are named in BruControl
*   globalReadValues - Values for each global variable
*
***********************************************************************************/
void getGlobals() {
  int i;
  for(i=0; i<READSIZE; i++) {
    globalReadValues[i] = getVariableValue(globalsToRead[i]);
    Serial.print("     readString Is: ");
    Serial.print(globalsToRead[i]);
    Serial.print(", ");
    Serial.println(globalReadValues[i]);
  }
}


/**********************************************************************************
* sendGlobals()
*
* Framework function to iterate through the array of BruControl global variables
* to send updates to.
*
* This function will send all global variables in the globalsToWrite array with
* corresponding values from the globalValuesToWrite array.
*
* Do not modify this function. Instead set the following at the top of this file:
*   WRITESIZE - number of global variables to update
*   globalsToWrite - names of global variables as they are named in BruControl
*   globalValuestoWrite - Values for each global variable
*
***********************************************************************************/
void sendGlobals() {
  int i;
  for(i=0; i<WRITESIZE; i++) {
    sendVariableValue(globalsToWrite[i], globalValuesToWrite[i]);
    Serial.print("     Write: ");
    Serial.print(globalsToWrite[i]);
    Serial.print(", ");
    Serial.println(globalValuesToWrite[i]);
  }
}


/**********************************************************************************
* getVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*
* Framework function to get values of individual BruControl global variables.
* This function is called by the getGlobals() framework function.
* The user should not call this function directly
*
* returns value of global variable in String form
*
***********************************************************************************/
String getVariableValue(String globalVariable) {
  String payload = "";
  StaticJsonDocument<512> jsonDoc;
  char temp1[100];
  char temp2[100];

  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;
   
    globalVariable.toCharArray(temp1,100);
    sprintf(temp2, "/global/%s", temp1);
    if (http.begin(client, serverAddress, port, temp2)) {
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }  
  payload.toCharArray(temp1,300);
  DeserializationError error = deserializeJson(jsonDoc, temp1);
  if(error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return "";
  }
  const char* returnValue = jsonDoc["Value"];
  return returnValue;
}


/**********************************************************************************
* sendVariableValue()
*   globalVariable - name of global variable as it appear in BruControl.
*   variableValue - value of variable in string form to send back to BruControl.
*
* Framework function to send updates to individual BruControl global variables.
* This function is called by the sendGlobals() framework function.
* The user should not call this function directly
*
***********************************************************************************/
void sendVariableValue(String globalVariable, String variableValue) {
  char temp1[100];
  char temp2[100];
  char temp3[100];

  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;

    globalVariable.toCharArray(temp1,100);
    variableValue.toCharArray(temp2,100);
    sprintf(temp3, "[{\"Name\":\"%s\",\"Value\":\"%s\"}]", temp1, temp2);
    String jsonToWrite = temp3;

    if (http.begin(client, serverAddress, port, "/globals")) {  // HTTP
      http.addHeader("Content-Type", "application/json");
      http.addHeader("Content-Length", String(jsonToWrite.length()));
      // start connection and send HTTP header
      int httpCode = http.PUT(jsonToWrite);
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
        }
      } else {
        Serial.printf("[HTTP] PUT... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
}

Capture.PNG
 
Last edited:
Seeing this error:
could not convert '(String*)(& globalsToRead)' from 'String*' to 'String'
 

Attachments

  • Capture.PNG
    Capture.PNG
    41.1 KB · Views: 11
FYI that does not work out of the gate. It will not connect to wifi.
If I define:
#ifndef STASSID
#define STASSID "SSID"
#define STAPSK "PASSWORD"

const char* ssid = STASSID;
const char* password = STAPSK;

It then works, so it appears something is up.
 
I have 3 devices running this same code for the wifi and don't have any issues connecting. Must be something specific to your wifi network.
 
My guess is the code copy/paste. When troubleshooting I tried your Hop dropper code and it errored somewhere (not wifi) as well.
 
I wrote an Arduino sketch for the nodeMCU that can be used to enable unsupported interfaces/devices in BruControl. Hopefully other people out there can make some use of it as well.

That is awesome! I have a fan that I want to turn on when approaching boil. I was thinking of using a NodeMCU for that purpose, this would make it much easier!
 
Back
Top