Enhancing Functionality with IoT Studio User Functions

In addition to basic control through MQTT, extra logic can be defined in the IoT platform to automate actions based on the data received from sensors.

User Functions provide the capability to execute custom business rules by writing code, and automatically deploying the code without provisioning servers, building an API, or maintaining the infrastructure.
Note: To access the data stored in AnythingDB to build some logic using the user Functions you will first need to create an App (an App is a set of permissions needed to ensure that the access to data is secure and that the user is authorized to perform the request).
  1. Click Access Control > Apps and create a new App by following these steps
  2. For this project, choose all the scopes so the app can be used for any purpose.
  3. Access the Authorization tab and add role::root.
    This will allow all the sections and resources of your application to read, create, update and delete.
  4. As the App Client ID and Client Secret are required in the functions, you should save them in the Variables Storage section under Space Settings. Make sure you enable the Function Access.
    Tip: To use the codes that are part of this project, make sure you have stored the app credentials as a variable called master-app.
  5. Below are sample codes to define logic rules or automated events:
    Note: Make sure you enter your own values for space and thing_uid on each code.
    1. high-temperature-event: An event is published when the temperature is above 30ºC.
      import json
      from iots import API
      from function import variables
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      def handle(req):
      
          if variables.exists("master-app"):
              my_client_id = variables.get("master-app")["client_id"]
              my_client_secret = variables.get("master-app")["client_secret"]
      
          body = req.body.decode("utf-8")
          body = json.loads(body)
          Temperature = body['Temperature']
      
          with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
              if Temperature <= 30:
                  return {"status_code": 204}
      
              data = {
                  "HighTemperature": {
                      "data": {
                          "Temperature": Temperature
                      }
                  }
              }
      
              update_event = api.spaces(SPACE).things(THING_UID).events("HighTemperature").create(data)
      
          return {
              "status_code": 200,
              "body": data
          }
      
    2. high-humidity-event: An event is published when the humidity is above 50 %.
      import json
      from iots import API
      from function import variables
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      def handle(req):
      
          if variables.exists("master-app"):
              my_client_id = variables.get("master-app")["client_id"]
              my_client_secret = variables.get("master-app")["client_secret"]
         
          body = req.body.decode("utf-8")
          body = json.loads(body)
          Humidity = body['Humidity'] 
      
          with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
              if Humidity <= 50:
                  return {"status_code": 204}
      
              data = {
                  "HighHumidity": {
                      "data": {
                          "Humidity": Humidity
                      }
                  }
              }
      
              update_event = api.spaces(SPACE).things(THING_UID).events("HighHumidity").create(data)
      
          return {
              "status_code": 200,
              "body": data
          }
      
    3. fan-logic: Fan switches on automatically when temperature exceeds 30°C
      import json
      from function import variables
      import paho.mqtt.publish as publish
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      host = 'mqtt.swx.altairone.com'
      port = 1883
      
      topic_publish = 'spaces/{}/things/{}/properties'.format(SPACE, THING_UID )
      
      fan_status = False
      
      def handle(req):
      
          global fan_status
      
          if variables.exists("HomeMQTTCredentials"):
              username = variables.get("HomeMQTTCredentials")["username"]
              password = variables.get("HomeMQTTCredentials")["password"]
       
              
          body = req.body.decode("utf-8")
          body = json.loads(body)
          Temperature = body['Temperature']
              
          if Temperature is not None :
              if Temperature > 30 :
                  if not fan_status:
                      fan_status = True
                      publish.single(topic_publish, payload=json.dumps({"Fan-status": fan_status}), qos=2, retain=False, hostname=host, port=1883, client_id="", keepalive=120, will=None, auth={'username': username, 'password': password}, tls=None)
              elif fan_status:
                  fan_status = False
                  publish.single(topic_publish, payload=json.dumps({"Fan-status": fan_status}), qos=2, retain=False, hostname=host, port=1883, client_id="", keepalive=120, will=None, auth={'username': username, 'password': password}, tls=None)
                  
              return {
                  "status_code": 200,
                  "body": json.dumps({"Fan-status": fan_status})
              }
          else:
              return {
                  "status_code": 400,
                  "body": "Temperature not found in request body"
              }
    4. door-logic: Updates the status of the property and from the action that controls the door status
      import json
      from iots import API
      from function import variables
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      def handle(req):
      
          action = json.loads(req.body.decode('utf-8'))
      
          if variables.exists("master-app"):
              my_client_id = variables.get("master-app")["client_id"]
              my_client_secret = variables.get("master-app")["client_secret"]
      
          with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
              href = action["OpenCloseDoor"]["href"]
              action_id = href.split('/')[-1]
              print(action_id)
              input_action = action["OpenCloseDoor"]["input"]["command"]
              print(input_action)
      
              response = api.spaces(SPACE).things(THING_UID).properties().get()
              property_value = response["Door-status"]
              print(property_value)
      
              if input_action != property_value:
                 
                  payload_property = input_action
                  
                  
                  update_property = api.spaces(SPACE).things(THING_UID).properties("Door-status").update
                  print("property updated")
                  
                  payload_action = {
                      "OpenCloseDoor": {
                          "status": "Completed - Door Status has been successfully updated."
                      }
                  }
                  update_action = api.spaces(SPACE).things(THING_UID).actions("OpenCloseDoor", action_id).update(payload_action)
                  print("action updated")
      
              else:
                 
                  payload_action = {
                      "OpenCloseDoor": {
                          "status": "Completed - Door Status Unchanged"
                      }
                  }
                  update_action = api.spaces(SPACE).things(THING_UID).actions("OpenCloseDoor", action_id).update(payload_action)
                  print("action updated")
      
          return {
              "status_code": 200,
              "body": req.body.decode('utf-8')
          }
      
    5. send-gas-alert: An email is sent when the gas sensor is active.
      from iots import API
      import json
      from function import variables
      from swx.utils.email import EmailRequest
      from swx.auth.token import get_token
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing","email"]
      
      def handle(req):
      
              if variables.exists("master-app"):
                  my_client_id = variables.get("master-app")["client_id"]
                  my_client_secret = variables.get("master-app")["client_secret"]
      
              with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
                  
                  thing_properties = api.spaces(SPACE).things(THING_UID).properties().get()
                 
                  Gas_status = thing_properties['Gas-status']
      
                  if Gas_status == True:
                                
                      result = api.spaces(SPACE).communications().email().send({
                          "body": {
                              "html": "<p>YouR GAS sensor has detected an anomaly. Please check it or call emergency</p>"
                           },
                      "subject": "DANGER: GAS ALERT",
                      "to": [
                          "preinoso.altair@gmail.com"
                      ]
                      })
                      assert result.http_response().status_code == 202
              
              return {
                  "status_code": 200,
                  "body": "Email sent!"
              }
         
    6. logic-action-fan: Updates the status of the property and from the action that controls the fan status
      import json
      from iots import API
      from function import variables
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      def handle(req):
      
          action = json.loads(req.body.decode('utf-8'))
      
          if variables.exists("master-app"):
              my_client_id = variables.get("master-app")["client_id"]
              my_client_secret = variables.get("master-app")["client_secret"]
      
          with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
              href = action["TurnFanOnOff"]["href"]
              action_id = href.split('/')[-1]
              print(action_id)
              input_action = action["TurnFanOnOff"]["input"]["mode"]
      
              response = api.spaces(SPACE).things(THING_UID).properties().get()
              property_value = response["Fan-status"]
      
              if input_action != property_value:
                 
                  payload_property = input_action
                  
                  update_property = api.spaces(SPACE).things(THING_UID).properties("Fan-status").update(payload_property)
                  
                  payload_action = {
                      "TurnFanOnOff": {
                          "status": "Completed - Fan Status has been successfully updated."
                      }
                  }
                  update_action = api.spaces(SPACE).things(THING_UID).actions("TurnFanOnOff", action_id).update(payload_action)
      
              else:
                 
                  payload_action = {
                      "TurnFanOnOff": {
                          "status": "Completed - Fan Status Unchanged"
                      }
                  }
                  update_action = api.spaces(SPACE).things(THING_UID).actions("TurnFanOnOff", action_id).update(payload_action)
      
          return {
              "status_code": 200,
              "body": req.body.decode('utf-8')
          }
      
    7. gas-alarm-event: An event is published whenever the gas sensor is active
      import json
      from iots import API
      from function import variables
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      def handle(req):
      
          if variables.exists("master-app"):
              my_client_id = variables.get("master-app")["client_id"]
              my_client_secret = variables.get("master-app")["client_secret"]
         
          body = req.body.decode("utf-8")
          body = json.loads(body)
          Gas_status = body['Gas-status']
      
          with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
              if Gas_status == False:
                  return {"status_code": 204}
       
              data = {
                  "GasAlarm": {
                      "data": {
                          "Gas-status": Gas_status
                      }
                  }
              }
      
              update_event = api.spaces(SPACE).things(THING_UID).events("GasAlarm").create(data)
      
          return {
              "status_code": 200,
              "body": data
          }
      
    8. window-logic: Updates the status of the property and from the action that controls the window status
      import json
      from iots import API
      from function import variables
      
      SPACE = "enter-your-space-ID"
      THING_UID = "enter-your-thing-UID"
      
      my_scopes = ["thing"]
      
      def handle(req):
      
          action = json.loads(req.body.decode('utf-8'))
      
          if variables.exists("master-app"):
              my_client_id = variables.get("master-app")["client_id"]
              my_client_secret = variables.get("master-app")["client_secret"]
      
          
          with API().set_credentials(my_client_id, my_client_secret, my_scopes) as api:
              href = action["OpenCloseWindow"]["href"]
              action_id = href.split('/')[-1]
              print(action_id)
              input_action = action["OpenCloseWindow"]["input"]["status"]
              print(input_action)
      
              response = api.spaces(SPACE).things(THING_UID).properties().get()
              property_value = response["Window-status"]
      
              if input_action != property_value:
                 
                  payload_property = input_action
                              
                  update_property = api.spaces(SPACE).things(THING_UID).properties("Window-status").update(payload_property)
                  
                  payload_action = {
                      "OpenCloseWindow": {
                          "status": "Completed - Window Status has been successfully updated."
                      }
                  }
                  update_action = api.spaces(SPACE).things(THING_UID).actions("OpenCloseWindow", action_id).update(payload_action)
      
              else:
                 
                  payload_action = {
                      "OpenCloseWindow": {
                          "status": "Completed - Window Status Unchanged"
                      }
                  }
                  update_action = api.spaces(SPACE).things(THING_UID).actions("OpenCloseWindow", action_id).update(payload_action)
      
          return {
              "status_code": 200,
              "body": req.body.decode('utf-8')
          }