Facility humidity and temperature monitoring (AVTECH Room Alert 3E implementation in Ignition)

I needed to implement facility temperature and humidity recordings in Ignition. We selected AVTECH Room Alert 3E sensors (There are many other types available - this is just the one we chose). One of the things we liked about this solution is that it was POE, so only network drops were required to get operational - No additional power drops. We also liked that many add-on sensors that were available.

It looked like a simple way to get data from the AVTECH sensors was to pull the data with httpGet, parse the data with json.loads, put the data into tags with WriteAsync.

The json.loads data had a few different layers, so this is also a good example of multi-layered json messages. If necessary, review your json messages with a website like this: jsoneditoronline.org

After the script was working with a button, we moved the code to a server side timer script.

Here is the script we used to automatically grab the data into Ignition where it is useful for tracking our facility environment to product quality.

Some basic error handling is included - You should probably include more!

#############
import json

#To add more sensors, increase both sensor and tag lists
################################
# YOU MUST KEEP THE SENSOR 
#Web pages AND the SENSOR TAG List matched
################################

#The example below writes one sensor data to two different tag sets...  Example ONLY
#SensorList = ["http://192.168.0.10/getData.json", "http://192.168.0.11/getData.json"]
#TagList = ['[default]Facilities/TempHumiditySensors/RoomAlert/Room1', '[default]Facilities/TempHumiditySensors/RoomAlert/Room2']

SensorList = ["http://192.168.0.20/getData.json"]
TagList = ['[default]Facilities/TempHumiditySensors/RoomAlert/RoomA1']


for SensorNumber in range(len(SensorList)):

	TagDestination = TagList[SensorNumber]
	try:
		#print 'Trying to get data'
		source = system.net.httpGet( SensorList[SensorNumber], 1000 )
		#print ' get data end'
		Online = True
	except:
		print 'error'
		SerialNumber = 'offline'
		InternalCurrentT_F = -98.0
		ExternalCurrentT_F = -98.0
		humid = -2.0
		Online = False

	if  Online == True:
		#Sensor was reachable
		
		try:
			print source
			print TagDestination
			
			#Extract the JSON to Python
			pythonDecode = json.loads(source)
			
			#Get device Serial Number
			SerialNumber = pythonDecode["name"]	
			
			#Internal Sensor data
			SensorID=0
			SensorType0 = pythonDecode["sensor"][SensorID]["label"]
			Type = pythonDecode["sensor"][SensorID]["type"]
			if SensorType0 == 'Internal Sensor' and Type == 16:
				InternalCurrentT_F = pythonDecode["sensor"][SensorID]["tempf"]
			else:
				InternalCurrentT_F = -99.0
			
			#First External Sensor data (We only use type #38)
			SensorID = 1
			SensorType1 = pythonDecode["sensor"][SensorID]["label"]
			Type = pythonDecode["sensor"][SensorID]["type"]
			if SensorType1 == 'Ext Sensor 1' and Type == 38:
				ExternalCurrentT_F = pythonDecode["sensor"][SensorID]["tempf"]
				humid = pythonDecode["sensor"][SensorID]["humid"]
			else:
				#JSON Formatting issue
				ExternalCurrentT_F = -99.0
				humid = -1.0
		
		except:
			SerialNumber = 'COM_err'
			InternalCurrentT_F = -97.0
			ExternalCurrentT_F = -97.0
			humid = -3.0
		#End Try
	#End IF ONLINE == True:
	
	paths = [TagDestination + '/SerialNumber', TagDestination + '/LastUpdated', TagDestination + '/InternalTemp_Now',    TagDestination + '/ExternalTemp_Now',  TagDestination +  '/ExternalHumidity_Now']

	values = [SerialNumber, system.date.now(), InternalCurrentT_F, ExternalCurrentT_F, humid]

2 Likes

You can have an easier time with things if you use system.net.httpClient, which can parse the JSON of a response body for you. Something like this (plus some other refactoring):

# Dictionary mapping sensor URLs to output base tag path
sensor_map = {
    "http://192.168.0.20/getData.json": "[default]Facilities/TempHumiditySensors/RoomAlert/RoomA1"
}


def extract_data(data):
    serial_number = data["name"]

    sensor_id = 0
    sensor_label = data["sensor"][sensor_id]["label"]
    sensor_type = data["sensor"][sensor_id]["type"]
    if sensor_label == 'Internal Sensor' and sensor_type == 16:
        internal_temp = data["sensor"][sensor_id]["tempf"]
    else:
        internal_temp = -99.0

    sensor_id = 1
    sensor_label = data["sensor"][sensor_id]["label"]
    sensor_type = data["sensor"][sensor_id]["type"]
    if sensor_label == 'Ext Sensor 1' and sensor_type == 38:
        external_temp = data["sensor"][sensor_id]["tempf"]
        humidity = data["sensor"][sensor_id]["humid"]
    else:
        external_temp = -99.0
        humidity = -1.0

    return {
        'SerialNumber': serial_number,
        'LastUpdated': system.date.now(),
        'InternalTemp_Now': internal_temp,
        'ExternalTemp_Now': external_temp,
        'ExternalHumidity_Now': humidity
    }


client = system.net.httpClient()

for sensor_url, tag_destination in sensor_map.items():
    data = None
    try:
        response = client.get(sensor_url, timeout=1000)
        data = extract_data(response.json)
    except:
        system.util.getLogger("Sensor Data").error("Error getting data from sensor at URL: %s", sensor_url)
        data = {
            'SerialNumber': 'offline',
            'LastUpdated': system.date.now(),
            'InternalTemp_Now': -98.0,
            'ExternalTemp_Now': -98.0,
            'ExternalHumidity_Now': -2.0
        }

    system.tag.writeAsync(
        [tag_destination + '/' + path for path in data.keys()],
        data.values()
    )
3 Likes