mjcumming / HomieV3

Homie V3 Implementation in Python
MIT License
5 stars 7 forks source link

Lots and lots of "devices" = make a special device or use lots of nodes? #6

Closed psyciknz closed 4 years ago

psyciknz commented 5 years ago

I saw this old issue: https://github.com/mjcumming/HomieV3/issues/4

And followed up with your answer about the homie convention.....I think your idea of a bridge device is what I should look at.

I'm trying to convert an alarm....so if we think about that, that 32 zones, 2 partitions and a number of other devices. My initial try was each zone was a node.....but that means each node is making a new connection, with it's own attributes.

Now that I think about it, I think the alarm as one device and create logs of different properties for each of the zones.

So would I subclass the device_base and make my own device type? Make make up a way of adding all the properties to it?

psyciknz commented 5 years ago

Hmm I see the node code, how does a node relate to a device? And where can I add nodes (which I assume a single properties to one device?

psyciknz commented 5 years ago

So i have a class now, that inherits Device_Base... I've got all my alarm zones as Property_Contacts and I add them to the self.nodes.

But now I see that a node and different to a property, So I'm trying this:

try:
                node = self.get_node(label)
                self.logger.info("HOMIE: Found existing node for '%s'" % label)
                node.update_contact()
            except:
                #has a node so use it.
                self.logger.info("HOMIE: Adding new contact node for '%s'" % label) 
                try:
                    #move contact_node to class, and set each zone as a node.
                    node = Node_Contact(self,name=label)
                    node.id = label
                    self.add_node(node)

A label is all the zone names (about 32 of them), It seems to add all my nodes, and then once added, it picks up the node that then getsa value change, but I'm trying to update the contact value, and the update_contact method isn't there. I guess I can pull the property explicit, but it looks like it should be there.

mjcumming commented 5 years ago

The Homie convention specifies a Device as the root. Each device has one or more Nodes. Each node has one or more Properties. For your situation, you could start with a device that represents the alarm system, then add a node containing all of the contacts, and then add each zone as a property. If you post your device and node code here I'll have a look at what is missing.

psyciknz commented 5 years ago

I was thinking overnight, I wonder if it would be: Alarm = device Zones, partitions etc are nodes ( ie each zone/PIR sensor is its own node) Zone open, zone trouble are properties of a zone node..

That seems to be how jpbarraca/pai is set out structurally so seems to fit. And works for my brain.

psyciknz commented 5 years ago

So here's what I'm trying. I'm having to use the base object for most of them. The class I'm in is a subclass of Device_Base.

So for an item, element = zone, attribute= open and label = "Main Door PIR" (which gets sanitised to maindoorpir - after looking tat the device id assert you have)

       if element == 'zone' and (attribute == "open"): #or attribute == "alarm"):
            try:
                label_sanitised = label.replace('_','').lower()
                node = self.get_node(label_sanitised) 
                self.logger.info("HOMIE: Found existing node for '%s'" % label)
                if value:
                    node.set_property_value(attribute.lower(),"OPEN")
                else:
                    node.set_property_value(attribute.lower(),"CLOSED")
            except Exception as e:
                #has a node so use it.
                self.logger.info("HOMIE: Adding new contact node for '%s'" % label) 
                try:
                    #move contact_node to class, and set each zone as a node.
                    node = Node_Base(self,name=label,id=label_sanitised,type_=element)
                    #node.id = label
                    newProperty = Property_Contact(node,id=attribute.lower(),name=attribute)
                    node.add_property(newProperty)

                    #self.nodes[label] = node
                    self.add_node(node)
                except Exception as e:
                    self.logger.error("HOMIE: Error creating node: " + str(e))

It add the nodes (each pir) successfully, and pulls one to update it's value. But it's falling over on the node.set_property_value sayingAttributeError("'Node_Base' object has no attribute 'set_property_value'",) .

Any thoughts? (all code in this branch: https://github.com/psyciknz/pai/tree/homie )

psyciknz commented 5 years ago

Having all the subclass, apart from confusing wasn't working for me. So I've now made a new Device variable in my class: alarm_device. I've got mqtt started etc, and are adding the nodes and properties:

try:
    #move contact_node to class, and set each zone as a node.
    zone_node = Node_Base(self.alarm_Device,name=label,id=label_sanitised,type_=element)
    **newProperty = Property_Boolean(zone_node,attribute,attribute)**
    zone_node.add_property(newProperty)
    self.alarm_Device.add_node(zone_node)
except Exception as e:
    self.logger.error("HOMIE: Error creating node: " + str(e))

Bu ti have it get an assertion error here. I can see you validate the id (mine for the property is "open") which is fine, I see an assert node - which has just been created, but can't tell if this is the issue., and later an assert on the value, which I'm not setting at this point.

I'll commit the code and give it a rest for now....there's been a number of comments from me as you can see me working through various issues.

mjcumming commented 5 years ago

I'll dig more into this tomorrow - but I am on CST :)

Quick question, it looks like you are adding device dynamically as you get events from them? Is there a way to get a list of them first?

psyciknz commented 5 years ago

I'll dig more into this tomorrow - but I am on CST :)

No worries....there's a bit there.

Quick question, it looks like you are adding device dynamically as you get events from them? Is there a way to get a list of them first?

No, this is the first time I know what all the devices are (and depending who uses this implementation, they're not fixed between systems). I don't want to make it too easy!! :)

mjcumming commented 5 years ago

Changes below for your code - need to update to Homie3 0.1.2



            label_sanitised = label.replace('_','').lower()

            zone_node = self.alarm_Device.get_node (label_sanitised)
            if zone_node is None: # create node
                zone_node = Node_Base(self.alarm_Device,name=label,id=label_sanitised,type_=element)
                self.alarm_Device.add_node(zone_node)

            property_contact = zone_node.get_property (attribute.lower())
            if property_contact is None:
                property_contact = Property_Boolean(zone_node,attribute.lower(),attribute)
                zone_node.add_property(property_contact)

            property_contact.value = value```
psyciknz commented 5 years ago

Hi sorry, got busy.

I did an update from github of the library and tried that code you posted.

But there's still as exception being rasied when trying to get a node that doesn't (yet) exist. So not sure if there's something else I need to look at to make the get_node just return None.

psyciknz commented 5 years ago

So I've reverted my code and now I get an exception on a new property: newProperty = Property_Boolean(zone_node,attribute,attribute)

Where attribute = "open"

I had to make an alteration to your property_base.validate_id to:

r = re.compile(r'(^(?!\-)[a-z0-9\-]+(?<!\-)$)')

adding the r, as it complained about escaping the backspaces. What version of python are you running with? I've got 3.6.

mjcumming commented 5 years ago

I am running 3.7. According to the Homie convention, backspaces are not allowed in a device id.

Topic IDs An MQTT topic consists of one or more topic levels, separated by the slash character (/). A topic level ID MAY contain lowercase letters from a to z, numbers from 0 to 9 as well as the hyphen character (-).

A topic level ID MUST NOT start or end with a hyphen (-). The special character $ is used and reserved for Homie attributes. The underscore (_) is used and reserved for Homie node arrays.

mjcumming commented 5 years ago

None

The current release does check if the node exists or not - should not cause an exception. Please have a look at device_base.py line 165

        if node_id in self.nodes:
            return self.nodes [node_id]
        else:
            return None
psyciknz commented 5 years ago

Sorry, the backspace comment was in reference to the regex string. I copied your validate_id code, and my pylint flagged the regex string as needing escaping.

On Sat, 1 Jun 2019 at 00:22, Michael Cumming notifications@github.com wrote:

I am running 3.7. According to the Homie convention, backspaces are not allowed in a device id.

Topic IDs An MQTT topic consists of one or more topic levels, separated by the slash character (/). A topic level ID MAY contain lowercase letters from a to z, numbers from 0 to 9 as well as the hyphen character (-).

A topic level ID MUST NOT start or end with a hyphen (-). The special character $ is used and reserved for Homie attributes. The underscore (_) is used and reserved for Homie node arrays.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mjcumming/HomieV3/issues/6?email_source=notifications&email_token=ABI2I4ZC5PSIUVWXTSBX2CDPYEKBVA5CNFSM4HNIVII2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWVCHEA#issuecomment-497689488, or mute the thread https://github.com/notifications/unsubscribe-auth/ABI2I43XPGNT6GIXC5DGLV3PYEKBVANCNFSM4HNIVIIQ .

psyciknz commented 5 years ago

hmm I was definitely getting a KeyError when I called get with a new node that I had not created yet. I mean I can deal with it using the exception code, so not too fussed. My bigger problem is creating the property getting an assert error.

Is that a new thing or been there a while? I'm not that sure how to verify what version of code of your's I'm running. I just updated via pip (diret from your github/master) yesterday.

On Sat, 1 Jun 2019 at 00:25, Michael Cumming notifications@github.com wrote:

None

The current release does check if the node exists or not - should not cause an exception. Please have a look at device_base.py line 165

    if node_id in self.nodes:
        return self.nodes [node_id]
    else:
        return None```

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/mjcumming/HomieV3/issues/6?email_source=notifications&email_token=ABI2I45FJJ5A4AS5FW5JLXTPYEKM7A5CNFSM4HNIVII2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWVCNJQ#issuecomment-497690278, or mute the thread https://github.com/notifications/unsubscribe-auth/ABI2I46L7LFZS56W32SCYQTPYEKM7ANCNFSM4HNIVIIQ .

mjcumming commented 5 years ago

You can force pip to install a specific version

pip install Homie3==0.1.8

psyciknz commented 5 years ago

Updaed homie with the command above (any way of verifying the version?)

I'm still getting an assertionerror on:

newProperty = Property_Boolean(zone_node,id=attribute.lower(),name=attribute.lower(),value=value)

Where zone has just been created, and attribute = 'open' Whether it's the assert node or assert(validate_id) I can't tell.
Any way you can attach something to the asserts so i can tell which one it's failing on?

mjcumming commented 5 years ago

likely the id.

Can you print out the id before creating the property so we can see what characters are in it?

psyciknz commented 5 years ago

Here's the code:

self.logger.info("HOMIE: Adding new property boolean '%s'" % attribute) 
newProperty = Property_Boolean(zone_node,id=attribute.lower(),name=attribute.lower(),value=value)
zone_node.add_property(newProperty)

That logger line looks like:

INFO:PAI.paradox.interfaces.homie_mqtt_interface:HOMIE: Adding new property boolean 'open'

when run

mjcumming commented 5 years ago

it must be failing on zone_node - the property value "open" should work.

psyciknz commented 5 years ago

I’ve inserted all that assert code of yours in line with my node and property creation and the node was ok. But the property had an issue. But I think it was the defect string that it had an issue with.

Is there another way you can do these tests to throw and error and pass a message so we can know for sure?