Python Plugin Beta testers - please read this

Python and python framework

Moderator: leecollings

zak45
Posts: 952
Joined: Sunday 22 January 2017 11:37
Target OS: Windows
Domoticz version: V2024.4
Contact:

Re: Python Plugin Beta testers - please read this

Post by zak45 »

Sorry ...made a conclusion too fast ... problems still there :-(
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin Beta testers - please read this

Post by Dnpwwo »

@zak45,

You will need to post the current version of your script
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
zak45
Posts: 952
Joined: Sunday 22 January 2017 11:37
Target OS: Windows
Domoticz version: V2024.4
Contact:

Re: Python Plugin Beta testers - please read this

Post by zak45 »

yep.. here it is.
Attachments
plugin.py.txt
(11.05 KiB) Downloaded 109 times
zak45
Posts: 952
Joined: Sunday 22 January 2017 11:37
Target OS: Windows
Domoticz version: V2024.4
Contact:

Re: Python Plugin Beta testers - please read this

Post by zak45 »

Just FYI: it looks like oncommand is executed every 3* timeout(heartbeat) when devices are disconnected.
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin Beta testers - please read this

Post by Dnpwwo »

@zak45,

If your device is physically turned off then your isAlive function could take a while to fail (depending on the timeout you set) which I would guess to be the issue if your plugin works when it is connected but has issues when it is not.

I have a Samsung TV as well and saw that the TV disconnects after 10 seconds as well even if you request keep-alive in a HTTP 1.1 request

I made an onHeartbeat like this which will always complete in 2 seconds or less (i used to limit the ping to 1 second but sometimes I got false results):

Code: Select all

import sys
import subprocess

class BasePlugin:
    isConnected = False
    isFound = False

    def onHeartbeat(self):
        Domoticz.Debug("onHeartbeat called")
        if (self.isConnected != True):
            # TV actively disconnects afte 10 seconds so just ping to see if its still on.
            if (sys.platform == 'win32'):
                currentstate = subprocess.call('ping -n 1 -w 2000 '+ Parameters["Address"] + ' > nul 2>&1', shell=True)
            else:
                currentstate = subprocess.call('ping -q -c1 -W 2 '+ Parameters["Address"] + ' > /dev/null', shell=True)
            
            Domoticz.Debug("Pinging "+Parameters["Address"]+", returned "+str(currentstate)+".")
            if (currentstate == 0) and (self.isFound == False):
                self.isFound = True
                if (1 in Devices): UpdateDevice(1, 1, "On")
                Domoticz.Log("Ping request answered, Television is on.")
            if (currentstate != 0) and (self.isFound == True):
                self.isFound = False
                for Key in Devices:
                    UpdateDevice(Key, 0, "Off")
                Domoticz.Log("Ping request ignored, Television is off.")
I think the log is empty because the only UpdateDevice calls you make take the form of

Code: Select all

UpdateDevice(Key, 1, Devices[Key].sValue)
which means if sValue starts blank it will be blank forever. Set it to "Off" or "On" as appropriate.
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
zak45
Posts: 952
Joined: Sunday 22 January 2017 11:37
Target OS: Windows
Domoticz version: V2024.4
Contact:

Re: Python Plugin Beta testers - please read this

Post by zak45 »

@Dnpwwo
Thanks a lot... you point me on the right direction!!!!
timeout is the solution ;-)

have put this line in the script :
socket.setdefaulttimeout(5)

since that... all is working as expected :D

in fact when value of heartbeat < timeout this not work very well.
now i have:
Domoticz.heartbeat(10) and socket.setdefaulttimeout(5)

thanks again!
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin Beta testers - please read this

Post by Dnpwwo »

@zak45,

Glad I could help.

Something to bear in mind is that the approach you have used will mean that the Plugin Framework will be blocked for 50% of the time when your television is turned off. This is fine if this is the only plugin you use but if you plan to make your script available to others then it will be a problem because all other plugins will be slow to respond to commands or messages (up to 5 second delays to commands). My Samsung TV does not respond to the network when it is in standby (although I believe later models do) so this may happen quite often for some people.

The code that I posted is slightly better because it could block the framework for 2 seconds worse case but will normally block for much less regardless of tv state. I'm still thinking about better options for this.

Just something to think about
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
zak45
Posts: 952
Joined: Sunday 22 January 2017 11:37
Target OS: Windows
Domoticz version: V2024.4
Contact:

Re: Python Plugin Beta testers - please read this

Post by zak45 »

So... have thought about.
After different test, threading etc ...I have simply tried by puting my timeout to 1.
This run very stable.

The time necessary to detect TV is on take only a few ms:
Spoiler: show
2017-02-28 22:11:56.241 User: Admin initiated a switch command (643/Samsung TV Salon - Volume/Set Level)
2017-02-28 22:11:56.265 (Samsung TV Salon) Calling message handler 'onCommand'.
2017-02-28 22:11:56.265 (Samsung TV Salon) onCommand called for Unit 3: Parameter 'Off', Level: 0, Connected: True
2017-02-28 22:11:56.479 (Samsung TV Salon) Send key : KEY_MUTE
2017-02-28 22:11:56.479 (Samsung TV Salon - Volume) Updating device from 0:'0' to have values 0:'0'.
2017-02-28 22:11:56.551 (Samsung TV Salon) Update 0:'0' (Samsung TV Salon - Volume)
2017-02-28 22:11:56.551 (Samsung TV Salon) Number of Mute activation: 4
2017-02-28 22:11:56.551 (Samsung TV Salon - Volume) Updating device from 0:'0' to have values 10:'10'.
2017-02-28 22:11:58.978 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:11:58.982 (Samsung TV Salon) isAlive status :True
2017-02-28 22:12:05.739 (RFX433E) Temp + Humidity (433-TempSDB)
2017-02-28 22:12:07.762 (RFX433E) Temp + Humidity (433-TempSalon)
2017-02-28 22:12:08.985 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:12:08.989 (Samsung TV Salon) isAlive status :True
2017-02-28 22:12:11.795 (RFX433E) Temp + Humidity (433-TempExt)
2017-02-28 22:12:19.008 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:12:19.022 (Samsung TV Salon) isAlive status :True
2017-02-28 22:12:29.031 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:12:29.035 (Samsung TV Salon) isAlive status :True
2017-02-28 22:12:39.046 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:12:39.050 (Samsung TV Salon) isAlive status :True

when power Off:
Spoiler: show
2017-02-28 22:17:04.968 (Samsung TV Salon) Device has disconnected - Maybe PowerOff
2017-02-28 22:17:04.968 (Samsung TV Salon - Status) Updating device from 1:'On' to have values 0:'Off'.
2017-02-28 22:17:05.031 (Samsung TV Salon) Update 0:'Off' (Samsung TV Salon - Status)
2017-02-28 22:17:05.031 (Samsung TV Salon - Source) Updating device from 10:'10' to have values 0:'Off'.
2017-02-28 22:17:05.094 (Samsung TV Salon) Update 0:'Off' (Samsung TV Salon - Source)
2017-02-28 22:17:05.094 (Samsung TV Salon - Volume) Updating device from 10:'10' to have values 0:'Off'.
2017-02-28 22:17:05.154 (Samsung TV Salon) Update 0:'Off' (Samsung TV Salon - Volume)
2017-02-28 22:17:05.155 (Samsung TV Salon) isAlive status :False
2017-02-28 22:17:05.155 (Samsung TV Salon) Heartbeat interval set to: 10.
2017-02-28 22:17:06.730 (RFX433E) Temp + Humidity (433-TempSDB)
2017-02-28 22:17:13.500 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:17:14.501 (Samsung TV Salon) isAlive status :False
2017-02-28 22:17:18.036 (RFX433E) Temp + Humidity (433-TempSDBE)
2017-02-28 22:17:23.509 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:17:23.790 (RFX433E) Temp + Humidity (433-TempExt)
2017-02-28 22:17:24.111 (AeonStick) Light/Switch (Z-FenetreCuisineMvt)
2017-02-28 22:17:24.510 (Samsung TV Salon) isAlive status :False
2017-02-28 22:17:33.507 (Samsung TV Salon) Calling message handler 'onHeartbeat'.
2017-02-28 22:17:34.508 (Samsung TV Salon) isAlive status :False
2017-02-28 22:17:35.760 (RFX433E) Temp + Humidity (433-TempSalon)
this take only 1s as supposed.
Maybe the solution...??
will adopt this one for the moment.
Have put that on my production and no issue since few hours.

thanks again for help.
gerardvs
Posts: 81
Joined: Sunday 04 January 2015 0:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: Python Plugin Beta testers - please read this

Post by gerardvs »

Hi all,
Not sure this is a Python Plugins "system failure" but here's my problem.

I made a Python plugin which created a custom sensor. Almost everything works fine but unfortunately notifications on the device doesn't work. While investigating this I found an issue in the device ID.

Look at the following screenshot
Image

Idx 1 is created by the plugin. When I, just for testing purposes, update the device via the json url like "/json.htm?type=command&param=udevice&idx=1&nvalue=0&svalue=6" the second device is created with idx 2.
Please note the difference in ID.

Testing is done on Domoticz 3.6807. And for reference (only) the plugin can be found here https://github.com/seventer/raintocome

Can some tell me if this is a bug or feature or how to access a device when created from a plugin?

Thanks,
--Gerard
Last edited by gerardvs on Wednesday 01 March 2017 22:44, edited 1 time in total.
User avatar
G3rard
Posts: 669
Joined: Wednesday 04 March 2015 22:15
Target OS: -
Domoticz version: No
Location: The Netherlands
Contact:

Re: Python Plugin Beta testers - please read this

Post by G3rard »

Maybe that explains why the MQTT messsages aren't working for these devices as well.
https://www.domoticz.com/forum/viewtopic.php?t=16227
Not using Domoticz anymore
gerardvs
Posts: 81
Joined: Sunday 04 January 2015 0:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: Python Plugin Beta testers - please read this

Post by gerardvs »

Yes, this could indeed be the same problem. I think this is a Domoticz bug.

A look at the database
Image
The funny thing is that notifications on the ID with an extra leading 0 does work fine, on the one created by the plugin it doesn't.

So there is definitely a bug around the ID handling of devices.

--Gerard
User avatar
G3rard
Posts: 669
Joined: Wednesday 04 March 2015 22:15
Target OS: -
Domoticz version: No
Location: The Netherlands
Contact:

Re: Python Plugin Beta testers - please read this

Post by G3rard »

gerardvs wrote:Hi all,
Not sure this is a Python Plugins "system failure" but here's my problem.

I made a Python plugin which created a custom sensor. Almost everything works fine but unfortunately notifications on the device doesn't work. While investigating this I found an issue in the device ID.

Look at the following screenshot
Image

Idx 1 is created by the plugin. When I, just for testing purposes, update the device via the json url like "/json.htm?type=command&param=udevice&idx=1&nvalue=0&svalue=6" the second device is created with idx 2.
Please note the difference in ID.

Testing is done on Domoticz 3.6807. And for reference (only) the plugin can be found here https://github.com/seventer/raintocome

Can some tell me if this is a bug or feature or how to access a device when created from a plugin?

Thanks,
--Gerard
This could also be caused by the custom sensor for which sending notifications doesn't seem to work.
I have a custom sensor which is filled by a LUA script and I have enabled the notifications, but these are never send.
Maybe you can try to use a humidity sensor for the rain prediction and see if that sends notifications.

And I think we should find a good way to share the Python plugin scripts. That way your script and the scripts of others (a while ago I saw a post from someone who made a script for remotely turning a Windows PC on/off) can be shared. Maybe something for the mods to have a look at.
Not using Domoticz anymore
gerardvs
Posts: 81
Joined: Sunday 04 January 2015 0:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: Python Plugin Beta testers - please read this

Post by gerardvs »

ok, after a small dive into the code I found the problem (at least I think I did).
Both notifications and external json commands are working fine now on custom devices.

I reported the issue here https://github.com/domoticz/domoticz/issues/1287.

--Gerard
gerardvs
Posts: 81
Joined: Sunday 04 January 2015 0:01
Target OS: Raspberry Pi / ODroid
Domoticz version: latest-1
Location: /dev/null
Contact:

Re: Python Plugin Beta testers - please read this

Post by gerardvs »

Sorry to say but there are still multiple issues with the Python-Plugin system. Since this thread is becoming (too) long I will create a new one.
--Gerard
gysmo38
Posts: 50
Joined: Saturday 01 February 2014 13:42
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python Plugin Beta testers - please read this

Post by gysmo38 »

Hello,

I discover the pyhton plugin, it is a very good idea :)

I already create script to control Mistubishi AirCondition Unit with MELCloud service.

I would like to create it like a plugin. I think it will be easier fot others users to use it.

Is it possible to connect to https URL?

I start coding the plugin but I'm not sure how to connect to MELCloud.

I connect using https URL and receive JSON answer.

Code: Select all

# MELCloud Pluginè
# Author:     Gysmo, 2017
# Version: 0.1
#   
# Release Notes:
# v0.1 : Initial release
"""
<plugin key="MELCloud" version="0.1" name="AAA_MELCloud plugin" author="gysmo" wikilink="" externallink="http://www.melcloud.com">
    <params>
        <param field="Mode1" label="Login" width="200px" required="true" />
        <param field="Mode2" label="Password" width="200px" required="true" />
        <param field="Mode3" label="Unit" width="200px" required="true" />
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>
"""
import Domoticz
import base64

pluginState = "Not Ready"
socketOn = "FALSE"

def onStart():
	if Parameters["Mode6"] == "Debug":
		Domoticz.Debugging(1)
	if (len(Devices) == 0):
		# Creation of switches
		# Image ID: 7 for fan, 15 for Temp, 16 for Mode
		OptionsMode = "LevelActions:"+stringToBase64("||||")+";LevelNames:"+stringToBase64("Off|Warm|Cold|Vent|Dry|Auto")+";LevelOffHidden:ZmFsc2U=;SelectorStyle:MQ=="
		Domoticz.Device(Name="Mode", Unit=1, TypeName="Selector Switch", Image=16, Options=OptionsMode).Create()
		Domoticz.Log("Device for Mode created.")
		OptionsFan = "LevelActions:"+stringToBase64("||||")+";LevelNames:"+stringToBase64("Level1|Level2|Level3|Level4|Silent|Auto")+";LevelOffHidden:ZmFsc2U=;SelectorStyle:MQ=="
		Domoticz.Device(Name="Fan", Unit=2, TypeName="Selector Switch", Image=7, Options=OptionsFan).Create()
		Domoticz.Log("Device for FAN created.")
		OptionsTemp = "LevelActions:"+stringToBase64("||||")+";LevelNames:"+stringToBase64("16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31")+";LevelOffHidden:ZmFsc2U=;SelectorStyle:MQ=="
		Domoticz.Device(Name="Temp", Unit=3, TypeName="Selector Switch", Image=15, Options=OptionsTemp).Create()
		Domoticz.Log("Device for Temperature created.")

	# Define connexion to MELCloud
	Domoticz.Transport(Transport="TCP/IP", Address="app.melcloud.com", Port="443")
	Domoticz.Protocol("HTTP")
	Domoticz.Connect()

def onConnect(Status, Description):
	if (Status == 0):
		Domoticz.Debug("MELCloud plugin connected successfully.")
		postData = "AppVersion=1.9.3.0&Language=7&CaptchaChallange=&CaptchaResponse=&Persist=true&Email="+Parameters["Mode1"]+"&Password="+Parameters["Mode2"]
		Domoticz.Send(postData, "POST", "/Mitsubishi.Wifi.Client/Login/ClientLogin", {'Content-Length':str(len(postData))})
		pluginState = "GetAuth"
	else:
		pluginState = "Not Ready"
		Domoticz.Log("Failed to connect ("+str(Status)+") to: "+Parameters["Address"]+":"+Parameters["Port"])
		Domoticz.Debug("Failed to connect ("+str(Status)+") to: "+Parameters["Address"]+":"+Parameters["Port"]+" with error: "+Description)

def onMessage(Data, Status, Extra):
	Domoticz.Debug("Receive message from MELCloud")
	strData = Data.decode("utf-8", "ignore")
	Response = json.loads(strData)
	if ('ErrorId' in Response):
		Domoticz.Debug("Error in login MELCloud")
	elif ('LoginData.ContextKey' in Response):
		Domoticz.Debug("Login ok in MELCloud")

#def onHeartbeat():

#	Domoticz.Debug("onHeartbeat called")
#	if (pluginState == "Not Ready"):
#		Domoticz.Connect()
#	elif (pluginState == "Ready"):
#		GetSocketSettings()

# https://app.melcloud.com/Mitsubishi.Wifi.Client/Login/ClientLogin

def stringToBase64(s):
    return base64.b64encode(s.encode('utf-8')).decode("utf-8")
Thank for helping me.
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin Beta testers - please read this

Post by Dnpwwo »

@gysmo38,

Only HTTP is supported by the framework itself at the moment I'm afraid
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
gysmo38
Posts: 50
Joined: Saturday 01 February 2014 13:42
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python Plugin Beta testers - please read this

Post by gysmo38 »

Ok thank you for the reply

I am a newbie in dev.

Is it possible to create my own functions to manage the https connexion in the plugin?
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin Beta testers - please read this

Post by Dnpwwo »

@gysmo38,

You should be able to use any library for that but you should use it synchronously otherwise I don't know what will happen.
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
User avatar
gizmocuz
Posts: 2483
Joined: Thursday 11 July 2013 18:59
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Top of the world
Contact:

Re: Python Plugin Beta testers - please read this

Post by gizmocuz »

I think (dnpwwo correct me is i'm wrong), when you create your plugin as a 'class' object you could:

- create a thread, and after each xx seconds, poll the status yourself via http/https/tcp/udp/... and report this to domoticz
- when you receive a command from domoticz to turn something on/off, call (indeed async) http/http/...

This way you are completely free and you should have no dependency on domoticz for the transport layer to the real hardware
Quality outlives Quantity!
User avatar
Dnpwwo
Posts: 820
Joined: Sunday 23 March 2014 9:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Melbourne, Australia
Contact:

Re: Python Plugin Beta testers - please read this

Post by Dnpwwo »

@gizmocuz. @gysmo38,

I honestly don't know what is possible when it comes to threading and asynchronous operations. Overall the Domoticz implementation is single threaded and does nothing with the Global Interpreter Lock (GIL) which may be okay but may not. Have a look at https://wiki.python.org/moin/GlobalInterpreterLock.

Documentation about it is sparse and poor so I am interested to see what happens when people take this to the next level.
The reasonable man adapts himself to the world; the unreasonable one persists to adapt the world to himself. Therefore all progress depends on the unreasonable man. George Bernard Shaw
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest