The MachineQ Platform by Comcast is a powerful data collection and aggregation platform for the IoT. Connect your MachineQ data to Ubidots to develop and deploy Business Intelligence Apps in days not months. In this Ubidots UbiFunctions article, we will explore how to communicate your devices data with Machine Q then relay all data to Ubidots where it can be made intelligent and add value to your business.
Contents:
Ubidots Setup
Machine Q Setup
Sample Codes for Machine Q data parser function in UbiFunctions
* PREDEFINED DECODER - Python and NodeJS
* UNKNOWN DECODER - Python and NodesJS
1. Ubidots Setup
1. Create a function in your Ubidots account:
1.1 Click on "Function" from the "Devices" tab of your Ubidots header:
1.2 Click the blue "+" icon to create a new function:
1.3 Name the function that describes the type of device you're using. We recommend using the format "Brand-Reference", i.e. "mq-stm" or "mq-mqspark".
1.4. Select "POST" as method:
1.5. Click on "Make it live" to deploy an API endpoint URL containing the name of your function. You will find the updated URL in the Function as shown below:
1.6. Next, choose your preferred language (NodeJS or Python) and copy and paste inside the function the sample codes found below (.py if you choose python, .txt if you choose nodejs).
2. MACHINE Q Setup
1. From your home MachineQ dashboard, navigate to Output profiles
2. Create a new Output profile
3. Then click "ADD REST PROFILE"
4. Fill in with the following parameters:
URL: place the URL previously created in your Ubidots account (step 1.5.) here.
TokenType:
X-Auth-Token
TokenValue: Place your Ubidots Token here.
5. Complete the Output Profile Name with an identifier - we use "Ubidots" as an example.
NOTE: If you have multiples devices of different brands, it is recommend to assign the name of Output Profile based on the brand. For example, “ubidots-mqspark”
6. Click on "submit" at the bottom of the Output Profile to save your work.
7. Next, navigate to the Devices Section and Edit settings.
8. Edit your actual device's settings
9. Select a Decode Type (if you do not choose one, MQ will send the data as Hexadecimal and the function will not work properly) and choose the Ubidots Profile Output created in step 6.
IMPORTANT NOTE: The data can be received in different ways, PREDEFINED DECODER or UNKNOWN DECODER. Based on how the data is being sent use the respective code found at the bottom of this tutorial.
10. Submit and Save your device settings.
11. Return to Ubidots to see data reporting in your Device Section. Now it's time to develop your BI application with:
Sample Codes for Machine Q Function in Ubidots
1. Using a PREDEFINED DECODER
Python Sample Code
import requests
import time
import struct
import binascii
def parse_data(comcast_payload):
'''
parses the payload that comes from comcast and returns the Ubidots Token, DEVEUI
and the decoded_payload keys, below you can find a payload example
'''
ubi_token = comcast_payload.get("token", None)
ubi_device = comcast_payload.get("DevEUI", None)
ubi_payload = comcast_payload.get("decoded_payload", None)
return (ubi_token, ubi_device, ubi_payload)
def send_to_ubidots(token, device, payload):
'''
Function to send data to ubidots
'''
url = "http://industrial.api.ubidots.com"
url = "{}/api/v1.6/devices/{}".format(url, device)
headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
status = 400
attempts = 0
print("[INFO] attempting to send data to Ubidots")
while status >= 400 and attempts <= 5:
req = requests.post(url=url, headers=headers, json=payload)
status = req.status_code
attempts += 1
if status >= 400:
time.sleep(1)
if status == 200 or status == 201:
print("[INFO] Data posted properly")
return True
print("[ERROR] Could not post data")
return False
def main(comcast_payload):
print("[INFO] Attempting to decode data")
ubi_token, ubi_device, ubi_payload = parse_data(comcast_payload)
'''
Parse the incoming data from machineQ
'''
payload = ubi_payload
if ubi_payload is not None and ubi_device is not None:
result = send_to_ubidots(ubi_token, ubi_device, ubi_payload)
return {"status": result}
print("[ERROR] Could not send data to Ubidots")
return {"status": False}
NodeJS Sample Code
var request = require('request-promise');
async function main(args) {
/*
Parses the payload that comes from comcast. Returning:
- Ubidots TOKEN
- Device EUI
- Data already decoded
*/
// Get the token
var ubidots_token = args.token;
// Get the device label
var device_label = args.DevEUI;
// Get payload
var data = args.decoded_payload;
// Make POST request to Ubidots
var post_response = await send_to_ubidots(ubidots_token, device_label, data);
// Pass Ubidots' API response to the function' response
return post_response;
}
async function send_to_ubidots(ubidots_token, device_label, data) {
/*
Function to send data to ubidots
*/
var options = {
method: 'POST',
url: 'https://industrial.api.ubidots.com/api/v1.6/devices/' + device_label + '?force=true',
body: data,
json: true,
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': ubidots_token
}
};
return await request.post(options);
}
2. Using an UNKNOWN DECODER
The codes provided below show how to decode the hexadecimal data received from machineQ. Please note that this should be modified based on how the data is being sent from the device.
As an example let's suppose that the device used is sending the data: 0x1B37
, where the first byte is related to a temperature value and the latter to humidity value, resulting in...
Data sent: 0x1B = 27 (temperature), 0x37 = 55 (humidity)
Python Sample Code
import requests
import time
import struct
import binascii
def parse_data(comcast_payload):
'''
parses the payload that comes from comcast and returns the Ubidots Token, DEVEUI
and the decoded_payload keys, below you can find a payload example
'''
ubi_token = comcast_payload.get("token", None)
ubi_device = comcast_payload.get("DevEUI", None)
ubi_payload = comcast_payload.get("decoded_payload", None)
ubi_payload = ubi_payload["RawData"]
return (ubi_token, ubi_device, ubi_payload)
def send_to_ubidots(token, device, payload):
'''
Function to send data to ubidots
'''
url = "http://industrial.api.ubidots.com"
url = "{}/api/v1.6/devices/{}".format(url, device)
headers = {"X-Auth-Token": token, "Content-Type": "application/json"}
status = 400
attempts = 0
print("[INFO] attempting to send data to Ubidots")
while status >= 400 and attempts <= 5:
req = requests.post(url=url, headers=headers, json=payload)
status = req.status_code
attempts += 1
if status >= 400:
time.sleep(1)
if status == 200 or status == 201:
print("[INFO] Data posted properly")
return True
print("[ERROR] Could not post data")
return False
def main(comcast_payload):
print("[INFO] Attempting to decode data")
ubi_token, ubi_device, ubi_payload = parse_data(comcast_payload)
'''
Parse the incoming data from machineQ
'''
payload = ubi_payload
len_payload_odd = int(round(len(payload) / 2.0) * 2.0)
fill = payload.rjust(len_payload_odd, '0')
temp_value, hum_value = struct.unpack('b'*int(len_payload_odd / 2), binascii.unhexlify(fill))
'''
Build the payload to be posted
'''
ubi_payload = {"temperature": temp_value, "humidity": hum_value}
if ubi_payload is not None and ubi_device is not None:
result = send_to_ubidots(ubi_token, ubi_device, ubi_payload)
return {"status": result}
print("[ERROR] Could not send data to Ubidots")
return {"status": False}
NodeJS Sample Code
var request = require('request-promise');
async function main(args) {
/*
Parses the payload that comes from comcast. Returning:
- Ubidots TOKEN
- Device EUI
- Data (2 bytes)
*/
// Get Ubidots Token
var ubidots_token = args.token;
// Get the device label
var device_label = args.DevEUI;
// Get payload
var data = args.decoded_payload.RawData;
// Parsing data to be posted
var buf = new Buffer(data, 'hex');
var temperature = buf.readInt8(0);
var humidity = buf.readInt8(1);
// Build Payload
var payload = {"temperature": temperature, "humidity": humidity};
// Make POST request to Ubidots
var post_response = await send_to_ubidots(ubidots_token, device_label, payload);
// Pass Ubidots' API response to the function' response
return post_response;
}
async function send_to_ubidots(ubidots_token, device_label, data) {
/*
Function to send data to ubidots
*/
var options = {
method: 'POST',
url: 'https://industrial.api.ubidots.com/api/v1.6/devices/' + device_label + '?force=true',
body: data,
json: true,
headers: {
'Content-Type': 'application/json',
'X-Auth-Token': ubidots_token
}
};
return await request.post(options);
}
WARNING: Remember that the UNKNOWN DECODER codes needs to be updated following the structure of how your device is sending the data.
Other users also found useful: