Bring my Photon coding from tinkering to production

Hi all!

I have been fiddling quite a bit with my Photons and now I totally love it.
I am writing to check if you guys can suggest any kind of course / book / website where I can learn to make my Photon code more robust and production ready.

I wrote simple code, for example, to retrieve temperature data from multiple sensors and send it out to my server but I’d love to understand better how to make my code much more bullet proof, how to properly test it and so on.

In my case every 7 days the Photon goes to blinking green and stops working forcing me to reset it, I think it is related to my bad coding and checking on the forum I have found functions that allow you to check if Photon is connected and if not try to connect again to WiFi and Cloud.

This improvement allowed me to understand, even more, how my code is weak and took me into writing this question.

Any very specific suggestion (More Photon related than Arduino, just to be clear) would be really fantastic.

Thanks for your time and for sharing.

1 Like

could you post the code?

#include "HttpClient/HttpClient.h"
#include "spark-dallas-temperature/spark-dallas-temperature.h"
#include "OneWire/OneWire.h"
#define ONE_WIRE_BUS D2 // Data wire is plugged into port 2 on the Particle Photon
#define TEMPERATURE_PRECISION 9 // Temperature precision is set to 9


// HttpClient initialization
HttpClient http;
// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { "Accept" , "application/json" },
    { "Accept" , "*/*"},
    { NULL, NULL } // NOTE: Always terminate headers will NULL
};
http_request_t request;
http_response_t response;

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Declaring variables
double tempC = 0.0;
// Customize this variable if you need to change interval between data send actions
int interval_seconds = 300; // Seconds of interval between updates
// OTA status
String ota_status;

String method; // Currently only "get" and "post" are implemented
String hostname;
int port;
String path;

// sendHttpRequest function
void sendHttpRequest(String method, String hostname, int port, String path, String body)
{
    request.hostname = hostname;
    request.port = port;
    request.path = path;
    request.body = body;

    Serial.print("Method: " + method + "\n");
    Serial.print("Hostname: " + hostname + "\n");
    Serial.print("Port: " + String(port) + "\n");
    Serial.print("Path: " + path + "\n");
    Serial.print("Body: " + body + "\n");

    if (method == "post") {
        Serial.print("\nSending http request\n");
        http.post(request, response, headers);
        Serial.print("Application>\tResponse status: ");
        Serial.println(response.status);
        Serial.print("Application>\tHTTP Response Body: ");
        Serial.println(response.body);
      } else if (method == "get") {
        Serial.print("\nSending http request\n");
        http.get(request, response, headers);
        Serial.print("Application>\tResponse status: ");
        Serial.println(response.status);
        Serial.print("Application>\tHTTP Response Body: ");
        Serial.println(response.body);
      } else {
        Serial.print("Please check your method: only post and get are currently supported");
    }
}

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Arrays to hold device addresses
DeviceAddress sensor1, sensor2, sensor3;

void setup(void)
{

    sensors.begin();
    Serial.begin(9600); // Start serial port
    Serial.println("Temperature Sensors");

    // Start up the library
    sensors.begin();

    // Locate devices on the bus
    Serial.print("Locating devices...");
    Serial.print("Found ");
    Serial.print(sensors.getDeviceCount(), DEC);
    Serial.println(" devices.");

    // Report parasite power requirements
    Serial.print("Parasite power is: ");
    if (sensors.isParasitePowerMode()) Serial.println("ON");
    else Serial.println("OFF");

    if (!sensors.getAddress(sensor1, 0)) Serial.println("Unable to find address for Device 0");
    if (!sensors.getAddress(sensor2, 1)) Serial.println("Unable to find address for Device 1");
    if (!sensors.getAddress(sensor3, 2)) Serial.println("Unable to find address for Device 2");

    // Set the resolution to 9 bit
    sensors.setResolution(sensor1, TEMPERATURE_PRECISION);
    sensors.setResolution(sensor2, TEMPERATURE_PRECISION);
    sensors.setResolution(sensor3, TEMPERATURE_PRECISION);

}

void loop(void)
{

    // Call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus
    Serial.print("Requesting temperatures...");
    sensors.requestTemperatures();
    Serial.println("DONE");

    // Getting sensor 1 temperature
    sensors.requestTemperatures();
    delay (3000); // Wait to allow the sensor to be online
    tempC = sensors.getTempCByIndex(0);

    int try_number = 0; // Variable used to count how many times the temp is reread in case of a bad value
    // Getting sensor 1 temperature
    // Handle bad tempC value  
    while (try_number < 6) {
        if (tempC == -127 || tempC == 85) {
            sensors.requestTemperatures();          
            delay (1000); // Wait to allow the sensor to be online            
            tempC = sensors.getTempCByIndex(0);
            sendHttpRequest("get", "myip", 8080, "/ota/notification/temp_error", "");
            try_number++;
        };
        try_number = 0;
        break;
    };
    Serial.print("Sensor1: ");
    Serial.print(tempC);
    // Adding sensor 1 temperature to JSON result string
    String resultstr;
    resultstr = "{\"customer_1\": {\"sensor_1_temp\":";
    resultstr += String(tempC);

    // Getting sensor 2 temperature
    tempC = sensors.getTempCByIndex(1);
    // Handle bad tempC value  
    while (try_number < 6) {
        if (tempC == -127 || tempC == 85) {
            sensors.requestTemperatures();          
            delay (1000); // Wait to allow the sensor to be online            
            tempC = sensors.getTempCByIndex(0);
            sendHttpRequest("get", "myip", 8080, "/ota/notification/temp_error", "");            
            try_number++;
        };
        try_number = 0;
        break;
    };
    Serial.print("Sensor2: ");
    Serial.print(tempC);
    // Adding sensor 2 temperature to JSON result string
    resultstr += ", \"sensor_2_temp\":";
    resultstr += String(tempC);

    // Getting sensor 3 temperature
    tempC = sensors.getTempCByIndex(2);
    // Handle bad tempC value  
    while (try_number < 6) {
        if (tempC == -127 || tempC == 85) {
            sensors.requestTemperatures();          
            delay (1000); // Wait to allow the sensor to be online            
            tempC = sensors.getTempCByIndex(0);
            sendHttpRequest("get", "myip", 8080, "/ota/notification/temp_error", "");
            try_number++;
        };
        try_number = 0;
        break;
    };
    Serial.print("Sensor3: ");
    Serial.print(tempC);
    // adding sensor 3 temperature to JSON result string
    resultstr += ", \"sensor_3_temp\":";
    resultstr += String(tempC);

    // adding wifi signal data
    resultstr += ", \"wifi_strenght\":";
    resultstr += String(WiFi.RSSI());
    // close JSON
    resultstr += "}}";

    // sending out data using httpclient
    Serial.print("Sending data out...");
    sendHttpRequest("post", "myip", 80, "/sensor/test", resultstr);
    // Debug
    //sendHttpRequest("post", "myip", 8080, "/post_print", resultstr;

    // Check if OTA is enabled via http
    sendHttpRequest("get", "myip", 8080, "/ota", "");
    ota_status = response.body;
    
    // Check if WiFi is connected, if not try to connect  
    if (!WiFi.ready()) {
     WiFi.connect();
       delay(10000);
     sendHttpRequest("get", "168.235.144.244", 8080, "/ota/notification/wifi_error", "");
    }
   
   // Check if Particle cloud is connected, if not try to connect
   if (!Particle.connected()) {
       Particle.connect();
       delay(10000);
       sendHttpRequest("get", "myip", 8080, "/ota/notification/particle_cloud_error", "");
   }
       

      // Check if OTA update is enabled
      if (ota_status=="off") {
          // Turn off onboard led to show user that Photon is NOT in OTA update mode
          digitalWrite(D7, LOW);
          // Put Particle Photon in deep sleep for number of seconds specified in interval_seconds
          System.sleep(SLEEP_MODE_DEEP,interval_seconds);
      } else {
          // Turn on onboard led to show user that Photon is in OTA update mode
          digitalWrite(D7, HIGH);
          // Send notification
          Serial.print("Application>\tSending OTA on notification to user");
          sendHttpRequest("get", "myip", 8080, "/ota/notification/temp_error", "");
          Serial.print("Application>\tResponse status: ");
          Serial.println(response.status);
          Serial.print("Application>\tHTTP Response Body: ");
          Serial.println(response.body);
          // Delay number of seconds specified in interval_seconds (delay function accepts a value in milliseconds that is why * 1000)
          delay(interval_seconds * 1000);
      }

}

Thanks for taking time to checking it :smile:

https://www.amazon.com/Programming-Arduino-Getting-Started-Sketches/dp/1259641635 This book is one of my favorite Arduino books. It is a great reference for Arduino/C++, and much of the content is applicable for Photons.

This book also looks promising. https://www.amazon.com/Programming-Arduino-Next-Steps-Sketches/dp/0071830251

1 Like

Thanks, it is really appreciated!

I will buy the 1st one immediately :slight_smile:

1 Like