Send Data from Revolution Pi based on Raspberry Pi to ThingSpeak Platform

Asad Elmgerbi on 13 Apr 2022
Latest activity Reply by Vinod on 5 May 2022

Dears Good day. I am new in IoT and I need help I am looking for a code that I can run to transmit real-time data from Revolution Pi based on Raspberry Pi to Thingspeak. I have code I used before to transmit data from Revolution Pi based on Raspberry Pi to Wolkabout ( cloud platform). Nevertheless, due to license issues. I had to change to Thingspeak. Can you please help me to adjust the code so that I can use it with Thingspeak instead of Wolkabout. Here is the code .............Code start...............

import os
import random
import sys
import time
from urllib.request import urlopen
import wolk 
import revpimodio2
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.register_read_message import ReadInputRegistersResponse
  1. Sensors Keys device = wolk.Device(key="KDD", password="FDV7F12TSW")

wolk_device = wolk.WolkConnect(device, host="54.72.159.61", port=8883, ca_cert="ca_local_wolkabout.crt") # Establish a connection to the WolkAbout IoT Platform print("Connecting to WolkAbout IoT Platform") wolk_device.connect() rpi = revpimodio2.RevPiModIO(autorefresh=True)

  1. For Modbus RTU Connection #client = ModbusClient(method = 'rtu', port='/dev/ttyRS485', stopbits=1, bytesize=8, parity='E',baudrate=19200,timeout=1,strict=False) #connection = client.connect() #print(connection)

def main(): """Connect to WolkAbout IoT Platform and send a random sensor reading."""

    publish_period_seconds = 5
    # LS1 Level sensor 1 LS2 Level sensor 2 VS1 Velocity sensor 1 VS2 Velocity sensor 2
    while True:
        try:
            #first set of the sensors
            LS1 = rpi.io.InputValue_1.value*0.059056-205.825
            LS2 = rpi.io.InputValue_2.value*0.059056-205.825
            VS1 = rpi.io.InputValue_3.value*0.0025-10
            VS2 = rpi.io.InputValue_4.value*0.0025-10
            #sensors from RTU1
            #Temp1= (client.read_input_registers(58, 1, unit=1))
            #Temp2 = Temp1.registers
            #Temp = float(Temp2[0])/100
            Temp1 = rpi.io.Temperature.value/100
            Temp2 = rpi.io.Temperature2.value/100
            #mu1= (client.read_input_registers(66, 1, unit=1))
            #mu2 = mu1.registers
            #mu = float(mu2[0])/100
            mu1 = rpi.io.Viscosity.value/100
            mu2 = rpi.io.Viscosity2.value/100
            #rho1= (client.read_input_registers(74, 1, unit=1))
            #rho2 = rho1.registers
            #rho = float(rho2[0])/100
            rho1 = rpi.io.Density.value/100
            rho2 = rpi.io.Density2.value/100
            #publshing data
            #wolk_device.add_sensor_readings({"LS1": LS1,"LS2": LS2,"VS1": VS1,"VS2": VS2,"Temp1": Temp1,"rho1": rho1,"mu1": mu1,"Temp2": Temp2,"rho2": rho2,"mu2": mu2})
            print('Publishing "Level Sensor 1": ' + str(LS1))
            print('Publishing "Level Sensor 2": ' + str(LS2))
            print('Publishing "Velocity Sensor 1": ' + str(VS1))
            print('Publishing "Velocity Sensor 2": ' + str(VS2))
            print('Publishing "Temperature_RTU1": ' + str(Temp1))
            print('Publishing "Viscosity_RTU1": ' + str(mu1))
            print('Publishing "Density_RTU1": ' + str(rho1))
            print('Publishing "Temperature_RTU2": ' + str(Temp2))
            print('Publishing "Viscosity_RTU2": ' + str(mu2))
            print('Publishing "Density_RTU2": ' + str(rho2))
            #wolk_device.publish()
            time.sleep(publish_period_seconds)
        except KeyboardInterrupt:
            print("\tReceived KeyboardInterrupt. Exiting script")
            wolk_device.disconnect()
            sys.exit()

if _name_ == "__main__": main() ...............Code End................... Hope that you can help me. I have a fee account in Thingspeak, only 1 channel with 8 fields which is enough for my current project for time being. Wish you a nice day

Christopher Stapels
Christopher Stapels on 14 Apr 2022

Here is an example that helps with bulk data, you can read the regular write data code to see how to adapt it too your more simple scenario.

Here is another example using websockets and MQTT .

Asad Elmgerbi
Asad Elmgerbi on 19 Apr 2022

Hi Christopher. Thanks a lot for your quick response. I have followed the example and I faced one challenge so far , it is for this line url = https://api.thingspeak.com/channels/+channel_ID+"/bulk_update.json" # ThingSpeak server settings Shall I make changes to that line? Because when I run it , it gives me an error (SyntaxError: invalid syntax) Can you please give me a hint to solve it .

Christopher Stapels
Christopher Stapels on 19 Apr 2022 (Edited on 21 Apr 2022)

Wow, that's an error in our code, thanks for finding it. Make sure channel_ID is in quotes so that python thinks its a string. Then try this.

    channel_ID="6"
    url = "https://api.thingspeak.com/channels/" + channel_ID + "/bulk_update.json" # ThingSpeak server settings
Asad Elmgerbi
Asad Elmgerbi on 5 May 2022
Hi Christopher,
Thanks a lot for your support. The code works fine now. I have just small question regarding post and update data interval. Is it possible to set these 2 to be 5 second ? or the minmum is 15 second ?
Vinod
Vinod on 5 May 2022
You can set it to 1 second if you purchase a ThingSpeak license. With a free license, the update rate needs to be once every 15s or slower so you don't end up exceeding the rate allowed by your license.
Asad Elmgerbi
Asad Elmgerbi on 22 Apr 2022
Hi Christopher,
Thanks a lot for your help.
I have updated the code so that it can work with my devices.
Based on my opinion, it should be ok. However, it will be highly appreciable if you can check it and give me your feedback.
..........................Code start............................
import json
import time
import os
import psutil
import requests
import random
import sys
from urllib.request import urlopen
import revpimodio2
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.register_read_message import ReadInputRegistersResponse
#.....................................................................
last_connection_time = time.time() # Track the last connection time
last_update_time = time.time() # Track the last update time
posting_interval = 120 # Post data once every 2 minutes
update_interval = 15 # Update once every 15 seconds
write_api_key = "MFE22I1FQ5M48GRP" # Replace YOUR-CHANNEL-write_api_key with your channel write API key
channel_ID = "1705096" # Replace YOUR-channel_ID with your channel ID
url = "https://api.thingspeak.com/channels/" + channel_ID + "/bulk_update.json" # ThingSpeak server settings
message_buffer = []
#.....................................................................
def httpRequest():
# Function to send the POST request to ThingSpeak channel for bulk update.
global message_buffer
bulk_data = json.dumps({'write_api_key':write_api_key,'updates':message_buffer}) # Format the json data buffer
request_headers = {"User-Agent":"mw.doc.bulk-update (Raspberry Pi)","Content-Type":"application/json","Content-Length":str(len(bulk_data))}
# Make the request to ThingSpeak
try:
print(request_headers)
response = requests.post(url,headers=request_headers,data=bulk_data)
print (response) # A 202 indicates that the server has accepted the request
except e:
print(e.code) # Print the error code
message_buffer = [] # Reinitialize the message buffer
global last_connection_time
last_connection_time = time.time() # Update the connection time
#.........................................................................
def getData():
# Function that returns the CPU temperature and percentage of CPU utilization
LS1 = rpi.io.InputValue_1.value*0.059056-205.825
LS2 = rpi.io.InputValue_2.value*0.059056-205.825
VS1 = rpi.io.InputValue_3.value*0.0025-10
VS2 = rpi.io.InputValue_4.value*0.0025-10
mu1 = rpi.io.Viscosity.value/100
mu2 = rpi.io.Viscosity2.value/100
rho1 = rpi.io.Density.value/100
rho2 = rpi.io.Density2.value/100
Temp1 = rpi.io.Temperature.value/100
Temp2 = rpi.io.Temperature2.value/100
print('Publishing "Level Sensor 1": ' + str(LS1))
print('Publishing "Level Sensor 2": ' + str(LS2))
print('Publishing "Velocity Sensor 1": ' + str(VS1))
print('Publishing "Velocity Sensor 2": ' + str(VS2))
print('Publishing "Temperature_RTU1": ' + str(Temp1))
print('Publishing "Viscosity_RTU1": ' + str(mu1))
print('Publishing "Density_RTU1": ' + str(rho1))
print('Publishing "Temperature_RTU2": ' + str(Temp2))
print('Publishing "Viscosity_RTU2": ' + str(mu2))
print('Publishing "Density_RTU2": ' + str(rho2))
return LS1,LS2,VS1,VS2,mu1,mu2,rho1,rho2,Temp1,Temp2
#.................................................................
def updatesJson():
# Function to update the message buffer every 15 seconds with data.
# And then call the httpRequest function every 2 minutes.
# This examples uses the relative timestamp as it uses the "delta_t" parameter.
# If your device has a real-time clock, you can also provide the absolute timestamp
# using the "created_at" parameter.
global last_update_time
message = {}
message['delta_t'] = int(round(time.time() - last_update_time))
LS1,LS2,VS1,VS2,mu1,mu2,rho1,rho2,Temp1,Temp2 = getData()
message['field1'] = LS1
message['field2'] = LS2
message['field3'] = VS1
message['field4'] = VS2
message['field5'] = mu1
message['field6'] = mu2
message['field7'] = rho1
message['field8'] = rho2
global message_buffer
message_buffer.append(message)
# If posting interval time has crossed 2 minutes update the ThingSpeak channel with your data
if time.time() - last_connection_time >= posting_interval:
httpRequest()
last_update_time = time.time()
#..................................................
if __name__ == "__main__": # To ensure that this is run directly and does not run when imported
while True:
# If update interval time has crossed 15 seconds update the message buffer with data
if time.time() - last_update_time >= update_interval:
updatesJson()
........................................End ....................................