Help with bridging a Python script over to Losant

Hi,

I have a Python script that I would like to see if someone would be willing to look at and see if they could help me with bridging it over to Losant. I can post it here in the forums if so.

Thanks,

Mike

We have Python clients for connecting to our MQTT broker and for interacting with our REST API. If you’re not using those already I would suggest you start there.

If you’re having trouble after that, feel free to post a code sample and let us know the specific issue you’re having and we’ll be happy to take a look.

We use python (for pretty much everything) and don’t use the Losant python library.
We use the paho mqtt lib and our python agents either talk directly to Losant (TLS) or via a local mosquitto broker.

The only difference is the setup and connection type.

May be you should include a some detail on what you are trying to do.

Hi Tim,

I will paste the script below. One of the things I am not certain about would be how to bridge this over to Losant.

#!/usr/bin/env python
“”" \example x4m300_presence_simpleoutput.py
This is an example of how to set up and read presence single messages from the
X4M300 module with the ModuleConnector python wrapper.
“”"
from future import print_function
import numpy as np
import time
from pymoduleconnector import ModuleConnector
from pymoduleconnector.ids import *
from time import sleep
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish
import json

############### Define MQTT ##################

Broker = “raspberrypi.local”
pub_change_topic = “presence/human/change/livingroom”
pub_detail_topic = “presence/human/detail/livingroom”

def on_connect(client, userdata, flags, rc):
print("Connected MQTT with result code " + str(rc))

client = mqtt.Client()
client.connect(Broker, 1883, 60)
client.loop_start()

def publishChange(isPresent):

print("publishChange: " + str(isPresent))
client.publish(pub_change_topic, str(isPresent).lower(), 1)

#@rate_limited(5000)
def publishDetail(isPresent, presenceState, distance, signalQuality):

print("publishDetail: " + str(presenceState))
jsonObj = json.dumps({'isPresent': isPresent,
                      'presenceState': presenceState,
                      'distance': distance,
                      'signalQuality': signalQuality})

client.publish(pub_detail_topic, str(jsonObj), 0)

############### Define MQTT ##################

def x4m300_presence_simpleoutput(device_name, detection_zone=(0.5, 9), sensitivity=5, num_messages=0):

# User settings
detzone_start = detection_zone[0]
detzone_end = detection_zone[1]

presence_state_text = []
presence_state_text.append("No presence")
presence_state_text.append("Presence")
presence_state_text.append("Initializing")

mc = ModuleConnector(device_name, log_level=0)
x4m300 = mc.get_x4m300()

sleep(1)  # Allow for MC to read waiting messages from module.

try:
    # Make sure no profile is running.
    x4m300.set_sensor_mode(XTID_SM_STOP, 0)
    print("Stopped already running profile.")
except RuntimeError:
    # If not initialized, stop returns error. Still OK, just wanted to make sure the profile was not running.
    pass

# Now flush old messages from module
print("Flushing any old data.")
while x4m300.peek_message_presence_single():
    presence_single = x4m300.read_message_presence_single()

# Read module info
print("FirmwareID:", x4m300.get_system_info(XTID_SSIC_FIRMWAREID))
print("Version:", x4m300.get_system_info(XTID_SSIC_VERSION))
print("Build:", x4m300.get_system_info(XTID_SSIC_BUILD))
print("Serial number:", x4m300.get_system_info(XTID_SSIC_SERIALNUMBER))

print("Loading new profile.")
x4m300.load_profile(XTS_ID_APP_PRESENCE_2)

print("Selecting module output.")

############### Turn LED off ##################
x4m300.set_led_control(0, 0)
############### Turn LED off ##################

x4m300.set_output_control(XTS_ID_PRESENCE_SINGLE, 1)  # PresenceSingle
x4m300.set_output_control(
    XTS_ID_PRESENCE_MOVINGLIST, 0)  # PresenceMovingList

print("Setting user settings: DetectionZone = " + str(detzone_start) +
      " to " + str(detzone_end) + ", Sensitivity = " + str(sensitivity))
x4m300.set_detection_zone(detzone_start, detzone_end)
x4m300.set_sensitivity(sensitivity)

print("Start profile execution.")
x4m300.set_sensor_mode(XTID_SM_RUN, 0)  # Make sure no profile is running.

print("Waiting for data...")

############### Previous State Var ##################
lastPresenceState = ''
lastDistance = 0
lastSignalQuality = 0

presenceState = ''
distance = 0
signalQuality = 0
############### Previous State Var ##################

n = 0
while num_messages == 0 or n < num_messages:
    time.sleep(0.1)

    while x4m300.peek_message_presence_single():
        presence_single = x4m300.read_message_presence_single()

        ############### Call MQTT ##################

        presenceState = presence_state_text[presence_single.presence_state]
        distance = str(round(presence_single.distance, 2))
        signalQuality = str(presence_single.signal_quality)

        isPresent = True if presenceState == 'Presence' else False

        hasPresenceStateChanged = presenceState != lastPresenceState
        if hasPresenceStateChanged:
            publishChange(isPresent)

        if hasPresenceStateChanged or distance != lastDistance or signalQuality != lastSignalQuality:
            publishDetail(isPresent, presenceState,
                          distance, signalQuality)

        lastPresenceState = presenceState
        lastDistance = distance
        lastSignalQuality = signalQuality

        print("Presence ->"
              + " FrameCounter: " + str(presence_single.frame_counter)
              + ", State: " + presenceState
              + ", Distance: " + distance
              + ", SignalQuality: " + signalQuality
              )
        ############### Call MQTT ##################

        n += 1

x4m300.set_sensor_mode(XTID_SM_STOP, 0)

def main():
import sys
from optparse import OptionParser
parser = OptionParser()
parser.add_option(
“-d”,
“–device”,
dest=“device_name”,
help=“device file to use, example: python %s -d COM4” % sys.argv[0],
metavar=“FILE”)

parser.add_option(
    "-n",
    "--num-messages",
    dest="num_messages",
    type=int,
    default=0,
    help="how many messages to read (0 = infinite)",
    metavar="INT")

parser.add_option('-z', '--detection_zone', nargs=2, type='float',
                  help='Start and stop of detection zone.', metavar='START STOP',
                  default=(0.5, 9))

parser.add_option('-s', '--sensitivity', nargs=1, type='int',
                  help='Sensor Sensitivity.', metavar='SENSITIVITY',
                  default=5)

(options, args) = parser.parse_args()

if not options.device_name:
    print("Please specify a device name, example: python %s -d COM4" %
          sys.argv[0])
    sys.exit(1)
x4m300_presence_simpleoutput(**vars(options))

if name == “main”:
main()

Hi Mike

The first thing to consider is the mismatch between your topics for presence and how Losant works.

You should start by having a read up Losant’s topic structure.

its losant/<deviceid>/state to report the state of a device. The payload is a json formated set of key value pairs. Which is quite different to the structure of the topics in your sample code.

Think about what and why you want to report data to Losant and look at what you trying to achieve. Some of the implied state based on your topics would then translate into a name/value pair that is part of the payload.

1 Like