Development informations

How it work ?

The plugin use clients who send message through operator service. Operator could be any web service or hardware (in future stuff) Clients service are register by plugin and communicat with they by internal code. Header defined in plugin configuration is added at the top of message.

xPL messages

No xPL message handle, use only 0MQ

Existing clients service.

Developing new notification service

Plugin offer way to add new client service.

3 step are needed.

1 - Editin JSON file plugin

Some adding must be necessary to do in info.json file:

  • For an SMS web service just add your operator id in parameters, operator, key choices of device_types, instance notify.smsweb:

    ......
    "notify.smsweb" : {
            "description" : "Send SMS using web service phone operator.",
            "id" : "notify.smsweb",
            "name" : "SMS operator web service",
            "commands" : ["send_msg"],
            "sensors" : ["msg_status", "error_send"],
            "parameters" : [{
                    "key" : "to",
                                        "xpl": false,
                    "description" : "Phone number to send SMS.",
                    "type" : "string"
                },{
                    "key" : "operator",
                                        "xpl": false,
                    "description" : "Operator service.",
                    "type" : "enum",
                    "choices" : {
                        "Bouygues_sms-web" : "Bouygues service",
                        "Freemobile_sms-web" : "Freemobile service",
                        "Orange_sms-web" : "Orange service",
                        "SFR_sms-web" : "SFR service", # add coma
                        "My_NEW_OPERATOR" : "NEW service"  # add ligne
                        }
                },{
                    "key" : "login",
                                        "xpl": false,
                    "description" : "User login service.",
                    "type" : "string"
                },{
                    "key" : "pwd",
                                        "xpl": false,
                    "description" : "User password service.",
                    "type" : "string"
                }
            ]
        },
        .....
    
  • For a new service or hardware, create your own device_types

    "notify.mynewservice" : {
            "description" : "A simple description of service.",
            "id" : "notify.mynewservice",
            "name" : "Name service",
            "commands" : ["send_extendmsg or send_msg"], # chose type of message
            "sensors" : ["msg_status", "error_send"],
            "parameters" : [{
                    "key" : "to",                       # keep this key, identification of recipient
                                        "xpl": false,                       # set to false for don't use in xPL message
                    "description" : "A simple description of recipient.",
                    "type" : "string"
                },{
                    "key" : "key1",                     # a optional key needed by service, like user/login/....
                                        "xpl": false,                       # set to false for don't use in xPL message
                    "description" : "A simple description of function.",
                    "type" : "string"
                },{
                    "key" : "key2",                     # a optional key needed by service, like password/....
                                        "xpl": false,                       # set to false for don't use in xPL message
                    "description" : "A simple description of function.",
                    "type" : "string"
                },{
                    .....
                }
            ]
        }
    },
    

2 - Editing clients_devices.py file

File lib/clients_devices.py contains a BaseClientService python class who handle basic methodes. You create a new class inherit this base class and overwriting some methodes to get acces of this new service or hardware. There is 3 thinks to do in this file :

  • 1st : Add your new operator id in OPERATORS_SERVICE global variable.
    This id is the same than JSON file
OPERATORS_SERVICE =  ['SFR_sms-web', 'Orange_sms-web', 'Bouygues_sms-web', 'Freemobile_sms-web', 'Newtifry', My_NEW_OPERATOR]
  • 2nd : You have to add new client device class reference in CreateOperator methode.

    def CreateOperator(params, log = None):
        """ Create a device depending of operator, use instance class to get parameters.
            - Developer : add your python class derived from DeviceBase class."""
        ....
        elif params['operator'] == 'My_new_service' :
            from domogik_packages.plugin_notify.lib.mynewcodefile import MyNewClient
        newOperator = MyNewClient(params,  log)
        ....
    
  • 3rd : If you have ceated a new instance_type, you have to add new client getting specifique parameters in GetDeviceParams methode.

    def GetDeviceParams(Plugin, device):
        """ Return all internal parameters depending of instance_type.
            - Developer : add your instance_type proper parameters
                @param Plugin : Plugin base class reference for "get_parameter" methods access.
                    type : object class Plugin
                @param device :  domogik device data.
                    type : dict
                @return : parameters for creating or update ClientService object.
                        Value must contain at least keys :
                            - 'operator' = Selected from OPERATORS_SERVICE
                            - 'to' = Client reference, the same as global parameter 'to'
                    type : dict
        """
        ...
        elif device['device_type_id'] == 'newtifry.device':
            operator = 'My_NEW_OPERATOR'
            id = device['parameters']['to']['value']                                              # keep this line
            valueKey1 = device['parameters']['Key1']['value']                                     # Get your new device paramaters
            valuekey2 = device['parameters']['Key2']['value']                                     # Get your new device paramaters
            valuekey3 = Plugin.get_parameter(device, 'defaulttitle')                              # Get a Plugin config paramaters if needed
            if operator and device["name"] and id and valueKey1 and valuekey3:                    # check for none optional parameters
                    # Build a dict with parameters
                params = {'name': device["name"] , 'operator' : operator, 'to' : id, 'key1' : valueKey1, 'key2' : valuekey2, 'key3' : valuekey3}
                return params                                                                       # return your own parameters
        ...
    

Creating new client class

In a new python file place in lib :

  • Import BaseClientService from plugin lib
from client_devices import BaseClientService
  • Create your python class
class My_New_Client(BaseClientService):  # simply new class declaration
    def send(self, message):  # overwrite methodes class
    ......

Overwrite update methode

This method is called by plugin to update proper parameters, so set your own parameters in:

def update(self, params):
    """ Create or update internal data, must be overwrited if others params needed.
        @param params :  parameters from GetDeviceParams() of domogik device'.
            type : dict
    """
    BaseClientService.update(self, params)                    # keep this line to call basic method
    self.key1 = params['key1']                                # your parameter
    self.key2 = params['key2'] if 'key2' in params else None  # your parameter

Overwrite send methode

This method is called by plugin for sending message on service, She must return a dict with format : use self._log to log message in plugin log.

{
    'status' : <A simple text to say sended or not>,
    'error' : <Error cause or empty ('') if no error>
}
def send(self, message):
    """ Send message
        @param message : message dict data contain at least keys:
            - 'to' : recipient of the message
            - 'header' : header for message set in plugin configuration
            - 'body" : message
            - extra key defined in 'command' json declaration like 'title', priority', ....
        @return : dict = {'status' : <Status info>, 'error' : <Error Message>}
    """
    ...
    # write your own code for format message and send it.
    # using try / except should avoid failling plugin
    try :
      ...
    except :
        result = {'status': u"Message not sended", 'error':  u"Bad message format : {0}".format(message)}
        self._log.warning(u"{0} Message <{1}> not sended. {2}".format(self.to, message, traceback.format_exc()))  # use traceback in lo
    ...
    if message_Is_Sended : return {'status': 'Message sended :)', 'error': ''}
    else return {'status': 'Message not sended :(', 'error': 'Server not response .....'}