Page 10 of 12

Re: Python Plugin: Python Plugin Manager

Posted: Thursday 23 April 2020 13:45
by ycahome
This plugin dynamically get the current working dir.
Am not sure that is anything to do apart from replacing all references with direct paths, at least for getcwd()

Re: Python Plugin: Python Plugin Manager

Posted: Thursday 23 April 2020 15:21
by Decyph
How can it be that the command doesnt see the current working folder as it is set?
I will try to set static folders for the getcwd() command.

I already tried the following before:
Spoiler: show
secpoluserFile = str(os.getcwd()) + "/domoticz/plugins/PP-MANAGER/secpoluser.txt"
To add the extra domoticz folder.

Update:

I edited the plugin.py and it still refers to the wrong wcd in the log, it seems like somewhere in the update proces it goes wrong.

Plugin.py now:
Spoiler: show

# pp-manager - PythonPlugin Manager
#
# Author: ycahome, 2018
#
# Since (2018-02-23): Initial Version
#
#


"""
<plugin key="PP-MANAGER" name="Python Plugin Manager" author="ycahome" version="1.5.21" externallink="https://www.domoticz.com/forum/viewtopi ... 65&t=22339">
<description>
<h2>Python Plugin Manager v.1.5.21</h2><br/>
<h3>Features</h3>
<ul style="list-style-type:square">
<li>Install plugins</li>
<li>Update All/Selected plugins</li>
<li>Update Notification for All/Selected</li>
</ul>
<h3>----------------------------------------------------------------------</h3>
<h3>WARNING:</h3>
<h2> Auto Updating plugins without verifying their code</h2>
<h2> makes you system vulnerable to developer's code intensions!!</h2>
<h3>----------------------------------------------------------------------</h3>
<h2>NOTE: After selecting your options press "Update" button!!</h2>
</description>
<params>
<param field="Mode2" label="Plugin to install" width="200px">
<options>
<option label="Idle" value="Idle" default="true" />
<option label="Dummy Plugin" value="Dummy_Plugin"/>
<option label="Battery monitoring for Z-Wave nodes" value="BatteryLevel"/>
<option label="Buienradar.nl (Weather lookup)" value="Buienradar"/>
<option label="Chromecast plugin for Domoticz" value="ChromecastPlugin"/>
<option label="Crow Runner Alarm" value="AAPIPModule"/>
<option label="deCONZ bridge (For Conbee,Raspbee)" value="deCONZ"/>
<option label="Denon/Marantz Amplifier" value="Denon4306"/>
<option label="Disc usage" value="xfr_discusage"/>
<option label="Dutch earthquakes" value="xfr_aardbeving"/>
<option label="Eartquake EMSC Data" value="SeismicPortal"/>
<option label="ebusd bridge" value="ebusd"/>
<option label="EMS bus Wi-Fi Gateway" value="ems-gateway"/>
<option label="eQ-3 MAX!" value="eq3max"/>
<option label="Freebox Revolution" value="freeboxv6"/>
<option label="Global Cache 100" value="GC-100"/>
<option label="Homewizard" value="Homewizard"/>
<option label="Hive Plugin" value="HivePlug"/>
<option label="iDetect Presence Detection" value="iDetect"/>
<option label="IKEA Tradfri" value="IKEA-Tradfri"/>
<option label="Life 360 Presence" value="Life360"/>
<option label="Linky" value="Linky"/>
<option label="Meteo Alarm EU RSS Reader" value="MeteoAlarmEU"/>
<option label="Mikrotik RouterOS" value="mikrotik-routeros"/>
<option label="Moon Phases" value="MoonPhases"/>
<option label="MQTT discovery" value="MQTTDiscovery"/>
<option label="Onkyo AV Receiver" value="Onkyo"/>
<option label="OpenAQ" value="xfr_openaq"/>
<option label="Pi-hole summary" value="xfr_pihole"/>
<option label="PiMonitor" value="xfr-pimonitor"/>
<option label="Pioneer AVR" value="PioneerAVR"/>
<option label="RAVEn Zigbee energy monitor" value="RAVEn"/>
<option label="SmogTok Air Quality monitor" value="SmogTok"/>
<option label="SNMP Reader" value="SNMPreader"/>
<option label="Sonos Players" value="Sonos"/>
<option label="Sony Bravia TV (with Kodi remote)" value="sony"/>
<option label="Speedtest" value="xfr_speedtest"/>
<option label="Synology SurveillanceStation" value="SurveillanceStation"/>
<option label="SYSFS-Switches" value="SYSFS-Switches"/>
<option label="UPS Monitor" value="NUT_UPS"/>
<option label="Wan IP Checker" value="WAN-IP-CHECKER"/>
<option label="Xiaomi Mi Flower Mate" value="Mi_Flower_mate_plugin"/>
<option label="Xiaomi Mi Robot Vacuum" value="xiaomi-mi-robot-vacuum"/>
<option label="Xiaomi PM2.5 Sensor" value="XiaomiPM"/>
<option label="Yamaha AV Receiver" value="YamahaPlug"/>
<option label="Zigate plugin" value="Zigate"/>
<option label="Zigbee2Mqtt" value="Zigbee2Mqtt"/>
</options>
</param>
<param field="Mode4" label="Auto Update" width="175px">
<options>
<option label="All" value="All"/>
<option label="All (NotifyOnly)" value="AllNotify" default="true"/>
<option label="Selected" value="Selected"/>
<option label="Selected (NotifyOnly)" value="SelectedNotify"/>
<option label="None" value="None"/>
</options>
</param>
<param field="Mode5" label="Security Scan (Experimental)" width="75px">
<options>
<option label="True" value="True"/>
<option label="False" value="False" default="true" />
</options>
</param>
<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 os
import subprocess
import sys

import urllib
import urllib.request
import urllib.error
import re

import time

import platform

#from urllib2 import urlopen
from datetime import datetime, timedelta



class BasePlugin:
enabled = False
pluginState = "Not Ready"
sessionCookie = ""
privateKey = b""
socketOn = "FALSE"


def __init__(self):
self.debug = False
self.error = False
self.nextpoll = datetime.now()
self.pollinterval = 60 #Time in seconds between two polls
self.ExceptionList = []
self.SecPolUserList = {}

self.plugindata = {
# Plugin Key: [gitHub author, repository, plugin Text, Branch]
"Idle": ["Idle", "Idle", "Idle", "master"],
"Dummy_Plugin": ["ycahome", "Dummy_Plugin", "Dummy Plugin", "master"],
"BatteryLevel": ["999LV", "BatteryLevel", "Battery monitoring for Z-Wave nodes", "master"],
"Buienradar": ["ffes", "domoticz-buienradar", "Buienradar.nl (Weather lookup)", "master"],
"AAPIPModule": ["febalci", "DomoticzCrowAlarm", "Crow Runner Alarm", "master"],
"ChromecastPlugin": ["Tsjippy", "ChromecastPlugin", "Chromecast plugin for Domoticz", "master"],
"deCONZ": ["Smanar", "Domoticz-deCONZ", "deCONZ bridge (For Conbee,Raspbee)","master"],
"Denon4306": ["dnpwwo", "Domoticz-Denon-Plugin", "Denon/Marantz Amplifier", "master"],
"xfr_discusage": ["Xorfor", "Domoticz-Disc-usage-Plugin", "Disc usage", "master"],
"xfr_aardbeving": ["Xorfor", "Domoticz-LastDutchEarthquake-Plugin", "Dutch earthquakes", "master"],
"SeismicPortal": ["febalci", "DomoticzEarthquake", "Eartquake EMSC Data", "master"],
"ebusd": ["guillaumezin", "DomoticzEbusd", "ebusd bridge", "master"],
"ems-gateway": ["bbqkees", "ems-esp-domoticz-plugin", "EMS bus Wi-Fi Gateway", "master"],
"eq3max": ["mvzut", "maxcube-Domoticz-plugin", "eQ-3 MAX! Cube", "master"],
"freeboxv6": ["supermat", "PluginDomoticzFreebox", "Freebox V6 (Revolution)", "master"],
"GC-100": ["dnpwwo", "Domoticz-GlobalCache-Plugin", "Global Cache 100", "master"],
"Homewizard": ["rvdvoorde", "domoticz-homewizard", "Homewizard", "master"],
"HivePlug": ["imcfarla2003", "domoticz-hive", "Hive Plugin", "master"],
"iDetect": ["d-EScape", "Domoticz_iDetect", "iDetect Presence Detection", "master"],
"IKEA-Tradfri": ["moroen", "IKEA-Tradfri-plugin", "IKEA Tradfri", "master"],
"Life360": ["febalci", "DomoticzLife360", "Life 360 Presence", "master"],
"Linky": ["guillaumezin", "DomoticzLinky", "Linky", "master"],
"MeteoAlarmEU": ["ycahome", "MeteoAlarmEU", "Meteo Alarm EU RSS Reader", "master"],
"mikrotik-routeros": ["mrin", "domoticz-routeros-plugin", "Mikrotik RouterOS", "master"],
"MoonPhases": ["ycahome", "MoonPhases", "Moon Phases", "master"],
"MQTTDiscovery": ["emontnemery", "domoticz_mqtt_discovery", "MQTT discovery", "master"],
"Onkyo": ["jorgh6", "domoticz-onkyo-plugin", "Onkyo AV Receiver", "master"],
"xfr_openaq": ["Xorfor", "Domoticz-OpenAQ-Plugin", "OpenAQ", "master"],
"xfr_pihole": ["Xorfor", "Domoticz-Pi-hole-Plugin", "Pi-hole summary", "master"],
"xfr-pimonitor": ["Xorfor", "Domoticz-PiMonitor-Plugin", "PiMonitor", "master"],
"PioneerAVR": ["febalci", "DomoticzPioneerAVR", "Pioneer AVR", "master"],
"RAVEn": ["dnpwwo", "Domoticz-RAVEn-Plugin", "RAVEn Zigbee energy monitor", "master"],
"SmogTok": ["smogtok", "smogtokdomoticzplug", "SmogTok Air Quality monitor", "master"],
"SNMPreader": ["ycahome", "SNMPreader", "SNMP Reader", "master"],
"Sonos": ["gerard33", "sonos", "Sonos Players", "master"],
"sony": ["gerard33", "sony-bravia", "Sony Bravia TV (with Kodi remote)", "master"],
"Synology SurveillanceStation": ["lolautruche", "SurveillanceStationDomoticz", "Synology SurveillanceStation", "master"],
"xfr_speedtest": ["Xorfor", "Domoticz-Speedtest-Plugin", "Speedtest", "master"],
"SYSFS-Switches": ["flatsiedatsie", "GPIO-SYSFS-Switches", "SYSFS-Switches", "master"],
"NUT_UPS": ["999LV", "NUT_UPS", "UPS Monitor", "master"],
"WAN-IP-CHECKER": ["ycahome", "WAN-IP-CHECKER", "Wan IP Checker", "master"],
"Mi_Flower_mate_plugin": ["flatsiedatsie", "Mi_Flower_mate_plugin", "Xiaomi Mi Flower Mate", "master"],
"xiaomi-mi-robot-vacuum": ["mrin", "domoticz-mirobot-plugin", "Xiaomi Mi Robot Vacuum", "master"],
"XiaomiPM": ["febalci", "DomoticzXiaomiPM2.5", "Xiaomi PM2.5 Sensor", "master"],
"YamahaPlug": ["thomas-villagers","domoticz-yamaha", "Yamaha AV Receiver", "master"],
"Zigate": ["pipiche38", "Domoticz-Zigate", "Zigate plugin", "stable"],
"Zigbee2Mqtt": ["stas-demydiuk", "domoticz-zigbee2mqtt-plugin", "Zigbee2Mqtt", "master"],
}

return

def onStart(self):

Domoticz.Debug("onStart called")

if Parameters["Mode6"] == 'Debug':
self.debug = True
Domoticz.Debugging(1)
DumpConfigToLog()
else:
Domoticz.Debugging(0)


Domoticz.Log("Domoticz Node Name is:" + platform.node())
Domoticz.Log("Domoticz Platform System is:" + platform.system())
Domoticz.Debug("Domoticz Platform Release is:" + platform.release())
Domoticz.Debug("Domoticz Platform Version is:" + platform.version())
Domoticz.Log("Default Python Version is:" + str(sys.version_info[0]) + "." + str(sys.version_info[1]) + "." + str(sys.version_info[2]) + ".")

if platform.system() == "Windows":
Domoticz.Error("Windows Platform NOT YET SUPPORTED!!")
return


pluginText = ""
pluginAuthor = ""
pluginRepository = ""
pluginKey = ""

pluginKey = Parameters["Mode2"]
pluginAuthor = self.plugindata[pluginKey][0]
pluginRepository = self.plugindata[pluginKey][1]
pluginText = self.plugindata[pluginKey][2]
pluginBranch = self.plugindata[pluginKey][3] # GitHub branch to clone








if (Parameters["Mode5"] == 'True'):
Domoticz.Log("Plugin Security Scan is enabled")

# Reading secpoluserFile and populating array of values
secpoluserFile = "/home/domoticz/domoticz" + "/plugins/PP-MANAGER/secpoluser.txt"

Domoticz.Debug("Checking for SecPolUser file on:" + secpoluserFile)
if (os.path.isfile(secpoluserFile) == True):
Domoticz.Log("secpoluser file found. Processing!!!")

# Open the file
secpoluserFileHandle = open(secpoluserFile)

# use readline() to read the first line
line = secpoluserFileHandle.readline()

while line:
if mid(line,0,4) == "--->":
secpoluserSection = mid(line,4,len(line))
Domoticz.Log("secpoluser settings found for plugin:" + secpoluserSection)
if ((mid(line,0,4) != "--->") and (line.strip() != "") and (line.strip() != " ")):
Domoticz.Debug("SecPolUserList exception (" + secpoluserSection.strip() + "):'" + line.strip() + "'")
#SecPolUserList.append(line.strip())
#SecPolUserList[secpoluserSection].append(line.strip())
if secpoluserSection.strip() not in self.SecPolUserList:
self.SecPolUserList[secpoluserSection.strip()] = []
self.SecPolUserList[secpoluserSection.strip()].append(line.strip())
# use realine() to read next line
line = secpoluserFileHandle.readline()
secpoluserFileHandle.close()
Domoticz.Log("SecPolUserList exception:" + str(self.SecPolUserList))
else:
self.SecPolUserList = {"Global":[]}


i = 0
path = "/home/domoticz/domoticz" + "/plugins/"
for (path, dirs, files) in os.walk(path):
for dir in dirs:
if str(dir) != "":
#self.UpdatePythonPlugin(pluginAuthor, pluginRepository, str(dir))
#parseFileForSecurityIssues("/home/domoticz/domoticz" + "/plugins/PP-MANAGER/plugin.py")
if (os.path.isfile("/home/domoticz/domoticz" + "/plugins/" + str(dir) + "/plugin.py") == True):
self.parseFileForSecurityIssues("/home/domoticz/domoticz" + "/plugins/" + str(dir) + "/plugin.py", str(dir))
i += 1
if i >= 1:
break







# Reading exception file and populating array of values
exceptionFile = "/home/domoticz/domoticz" + "/plugins/PP-MANAGER/exceptions.txt"
Domoticz.Debug("Checking for Exception file on:" + exceptionFile)
if (os.path.isfile(exceptionFile) == True):
Domoticz.Log("Exception file found. Processing!!!")

# Open the file
f = open(exceptionFile)

# use readline() to read the first line
line = f.readline()

while line:

if ((line[:1].strip() != "#") and (line[:1].strip() != " ") and (line[:1].strip() != "")):
Domoticz.Log("File ReadLine result:'" + line.strip() + "'")
self.ExceptionList.append(line.strip())
# use realine() to read next line
line = f.readline()
f.close()
Domoticz.Debug("self.ExceptionList:" + str(self.ExceptionList))







if Parameters["Mode4"] == 'All':
Domoticz.Log("Updating All Plugins!!!")
i = 0
path = "/home/domoticz/domoticz" + "/plugins/"
for (path, dirs, files) in os.walk(path):
for dir in dirs:
if str(dir) != "":
if str(dir) in self.plugindata:
self.UpdatePythonPlugin(pluginAuthor, pluginRepository, str(dir))
elif str(dir) == "PP-MANAGER":
Domoticz.Debug("PP-Manager Folder found. Skipping!!")
else:
Domoticz.Log("Plugin:" + str(dir) + " cannot be managed with PP-Manager!!.")
i += 1
if i >= 1:
break

if Parameters["Mode4"] == 'AllNotify':
Domoticz.Log("Collecting Updates for All Plugins!!!")
i = 0
path = "/home/domoticz/domoticz" + "/plugins/"
for (path, dirs, files) in os.walk(path):
for dir in dirs:
if str(dir) != "":
if str(dir) in self.plugindata:
self.CheckForUpdatePythonPlugin(pluginAuthor, pluginRepository, str(dir))
elif str(dir) == "PP-MANAGER":
Domoticz.Debug("PP-Manager Folder found. Skipping!!")
else:
Domoticz.Log("Plugin:" + str(dir) + " cannot be managed with PP-Manager!!.")
i += 1
if i >= 1:
break

if (Parameters["Mode4"] == 'SelectedNotify'):
Domoticz.Log("Collecting Updates for Plugin:" + pluginKey)
self.CheckForUpdatePythonPlugin(pluginAuthor, pluginRepository, pluginKey)


if pluginKey == "Idle":
Domoticz.Log("Plugin Idle")
Domoticz.Heartbeat(60)
else:
Domoticz.Debug("Checking for dir:" + "/home/domoticz/domoticz" + "/plugins/" + pluginKey)
#If plugin Directory exists
if (os.path.isdir("/home/domoticz/domoticz" + "/plugins/" + pluginKey)) == True:
Domoticz.Debug("Folder for Plugin:" + pluginKey + " already exists!!!")
#Domoticz.Debug("Set 'Python Plugin Manager'/ 'Domoticz plugin' attribute to 'idle' in order t.")
if Parameters["Mode4"] == 'Selected':
Domoticz.Debug("Updating Enabled for Plugin:" + pluginText + ".Checking For Update!!!")
self.UpdatePythonPlugin(pluginAuthor, pluginRepository, pluginKey)
Domoticz.Heartbeat(60)
else:
Domoticz.Log("Installation requested for Plugin:" + pluginText)
Domoticz.Debug("Installation URL is:" + "https://github.com/" + pluginAuthor +"/" + pluginRepository)
Domoticz.Debug("Current Working dir is:" + "/home/domoticz/domoticz")
if pluginKey in self.plugindata:
Domoticz.Log("Plugin Display Name:" + pluginText)
Domoticz.Log("Plugin Author:" + pluginAuthor)
Domoticz.Log("Plugin Repository:" + pluginRepository)
Domoticz.Log("Plugin Key:" + pluginKey)
Domoticz.Log("Plugin Branch:" + pluginBranch)
self.InstallPythonPlugin(pluginAuthor, pluginRepository, pluginKey, pluginBranch)
Domoticz.Heartbeat(60)



def onStop(self):
Domoticz.Debug("onStop called")

Domoticz.Log("Plugin is stopping.")
self.UpdatePythonPlugin("ycahome", "pp-manager", "PP-MANAGER")
Domoticz.Debugging(0)

def onHeartbeat(self):
Domoticz.Debug("onHeartbeat called")
pluginKey = Parameters["Mode2"]

CurHr = str(datetime.now().hour)
CurMin = str(datetime.now().minute)
if len(CurHr) == 1: CurHr = "0" + CurHr
if len(CurMin) == 1: CurMin = "0" + CurMin
Domoticz.Debug("Current time:" + CurHr + ":" + CurMin)

if (mid(CurHr,0,2) == "12" and mid(CurMin,0,2) == "00"):
Domoticz.Log("Its time!!. Trigering Actions!!!")


#-------------------------------------
if Parameters["Mode4"] == 'All':
Domoticz.Log("Checking Updates for All Plugins!!!")
i = 0
path = "/home/domoticz/domoticz" + "/plugins/"
for (path, dirs, files) in os.walk(path):
for dir in dirs:
if str(dir) != "":
self.UpdatePythonPlugin(self.plugindata[Parameters["Mode2"]][0], self.plugindata[Parameters["Mode2"]][1], str(dir))
i += 1
if i >= 1:
break

if Parameters["Mode4"] == 'AllNotify':
Domoticz.Log("Collecting Updates for All Plugins!!!")
i = 0
path = "/home/domoticz/domoticz" + "/plugins/"
for (path, dirs, files) in os.walk(path):
for dir in dirs:
if str(dir) != "":
self.CheckForUpdatePythonPlugin(self.plugindata[Parameters["Mode2"]][0], self.plugindata[Parameters["Mode2"]][1], str(dir))
i += 1
if i >= 1:
break

if Parameters["Mode4"] == 'SelectedNotify':
Domoticz.Log("Collecting Updates for Plugin:" + pluginKey)
self.CheckForUpdatePythonPlugin(self.plugindata[Parameters["Mode2"]][0], self.plugindata[Parameters["Mode2"]][1], Parameters["Mode2"])

#-------------------------------------
if Parameters["Mode4"] == 'Selected':
Domoticz.Log("Checking Updates for Plugin:" + self.plugindata[pluginKey][2])
self.UpdatePythonPlugin(self.plugindata[Parameters["Mode2"]][0], self.plugindata[Parameters["Mode2"]][1], Parameters["Mode2"])

#if Parameters["Mode2"] == "Idle":
#Domoticz.Log("Plugin Idle. No actions to be performed!!!")










# InstallPyhtonPlugin function
def InstallPythonPlugin(self, ppAuthor, ppRepository, ppKey, ppBranch):
Domoticz.Debug("InstallPythonPlugin called")


Domoticz.Log("Installing Plugin:" + self.plugindata[ppKey][2])
ppCloneCmd = "LANG=en_US /usr/bin/git clone -b " + ppBranch + " https://github.com/" + ppAuthor + "/" + ppRepository + ".git " + ppKey
Domoticz.Log("Calling:" + ppCloneCmd)
try:
pr = subprocess.Popen( ppCloneCmd , cwd = os.path.dirname("/home/domoticz/domoticz" + "/plugins/"), shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE )
(out, error) = pr.communicate()
if out:
Domoticz.Log("Succesfully installed:" + str(out).strip)
Domoticz.Log("---Restarting Domoticz MAY BE REQUIRED to activate new plugins---")
if error:
Domoticz.Debug("Git Error:" + str(error))
if str(error).find("Cloning into") != -1:
Domoticz.Log("Plugin " + ppKey + " installed Succesfully")
except OSError as e:
Domoticz.Error("Git ErrorNo:" + str(e.errno))
Domoticz.Error("Git StrError:" + str(e.strerror))

#try:
# pr1 = subprocess.Popen( "/etc/init.d/domoticz.sh restart" , cwd = os.path.dirname("/home/domoticz/domoticz" + "/plugins/"), shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE )
# (out1, error1) = pr1.communicate()
# if out1:
# Domoticz.Log("Command Response1:" + str(out1))
# if error1:
# Domoticz.Log("Command Error1:" + str(error1.strip()))
#except OSError1 as e1:
# Domoticz.Error("Command ErrorNo1:" + str(e1.errno))
# Domoticz.Error("Command StrError1:" + str(e1.strerror))


return None




# UpdatePyhtonPlugin function
def UpdatePythonPlugin(self, ppAuthor, ppRepository, ppKey):
Domoticz.Debug("UpdatePythonPlugin called")

if ppKey == "PP-MANAGER":
Domoticz.Log("Self Update Initiated")
ppGitReset = "LANG=en_US /usr/bin/git reset --hard HEAD"
try:
pr = subprocess.Popen( ppGitReset , cwd = "/home/domoticz/domoticz" + "/plugins/" + ppKey, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE )
(out, error) = pr.communicate()
if out:
Domoticz.Debug("Git Response:" + str(out))
if error:
Domoticz.Debug("Git Error:" + str(error.strip()))
except OSError as eReset:
Domoticz.Error("Git ErrorNo:" + str(eReset.errno))
Domoticz.Error("Git StrError:" + str(eReset.strerror))



elif (self.plugindata[ppKey][2] in self.ExceptionList):
Domoticz.Log("Plugin:" + self.plugindata[ppKey][2] + " excluded by Exclusion file (exclusion.txt). Skipping!!!")
return

Domoticz.Log("Updating Plugin:" + ppKey)
ppUrl = "LANG=en_US /usr/bin/git pull --force"
Domoticz.Debug("Calling:" + ppUrl + " on folder " + "/home/domoticz/domoticz" + "/plugins/" + ppKey)
try:
pr = subprocess.Popen( ppUrl , cwd = "/home/domoticz/domoticz" + "/plugins/" + ppKey, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE )
(out, error) = pr.communicate()
if out:
Domoticz.Debug("Git Response:" + str(out))
if (str(out).find("Already up-to-date") != -1) or (str(out).find("Already up to date") != -1):
Domoticz.Log("Plugin " + ppKey + " already Up-To-Date")
#Domoticz.Log("find(error):" + str(str(out).find("error")))
elif (str(out).find("Updating") != -1) and (str(str(out).find("error")) == "-1"):
ppUrl = "chmod "
Domoticz.Log("Succesfully pulled gitHub update:" + str(out)[str(out).find("Updating")+8:26] + " for plugin " + ppKey)
Domoticz.Log("---Restarting Domoticz MAY BE REQUIRED to activate new plugins---")
else:
Domoticz.Error("Something went wrong with update of " + str(ppKey))
if error:
Domoticz.Debug("Git Error:" + str(error.strip()))
if str(error).find("Not a git repository") != -1:
Domoticz.Log("Plugin:" + ppKey + " is not installed from gitHub. Cannot be updated with PP-Manager!!.")
except OSError as e:
Domoticz.Error("Git ErrorNo:" + str(e.errno))
Domoticz.Error("Git StrError:" + str(e.strerror))

return None





# UpdateNotifyPyhtonPlugin function
def CheckForUpdatePythonPlugin(self, ppAuthor, ppRepository, ppKey):
Domoticz.Debug("CheckForUpdatePythonPlugin called")

if (self.plugindata[ppKey][2] in self.ExceptionList):
Domoticz.Log("Plugin:" + self.plugindata[ppKey][2] + " excluded by Exclusion file (exclusion.txt). Skipping!!!")
return

Domoticz.Debug("Checking Plugin:" + ppKey + " for updates")


#Domoticz.Log("Fetching Repository Details")
ppGitFetch = "LANG=en_US /usr/bin/git fetch"
try:
prFetch = subprocess.Popen( ppGitFetch , cwd = "/home/domoticz/domoticz" + "/plugins/" + ppKey, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE )
(outFetch, errorFetch) = prFetch.communicate()
if outFetch:
Domoticz.Debug("Git Response:" + str(outFetch))
if errorFetch:
Domoticz.Debug("Git Error:" + str(errorFetch.strip()))
except OSError as eFetch:
Domoticz.Error("Git ErrorNo:" + str(eFetch.errno))
Domoticz.Error("Git StrError:" + str(eFetch.strerror))


ppUrl = "LANG=en_US /usr/bin/git status -uno"
Domoticz.Debug("Calling:" + ppUrl + " on folder " + "/home/domoticz/domoticz" + "/plugins/" + ppKey)

try:
pr = subprocess.Popen( ppUrl , cwd = "/home/domoticz/domoticz" + "/plugins/" + ppKey, shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE )
(out, error) = pr.communicate()
if out:
Domoticz.Debug("Git Response:" + str(out))
if (str(out).find("up-to-date") != -1) or (str(out).find("up to date") != -1):
Domoticz.Log("Plugin " + ppKey + " already Up-To-Date")
Domoticz.Debug("find(error):" + str(str(out).find("error")))
elif (str(out).find("Your branch is behind") != -1) and (str(str(out).find("error")) == "-1"):
Domoticz.Log("Found that we are behind on plugin " + ppKey)
self.fnSelectedNotify(ppKey)
elif (str(out).find("Your branch is ahead") != -1) and (str(str(out).find("error")) == "-1"):
Domoticz.Debug("Found that we are ahead on plugin " + ppKey + ". No need for update")
else:
Domoticz.Error("Something went wrong with update of " + str(ppKey))
if error:
Domoticz.Debug("Git Error:" + str(error.strip()))
if str(error).find("Not a git repository") != -1:
Domoticz.Log("Plugin:" + ppKey + " is not installed from gitHub. Ignoring!!.")
except OSError as e:
Domoticz.Error("Git ErrorNo:" + str(e.errno))
Domoticz.Error("Git StrError:" + str(e.strerror))

return None



# fnSelectedNotify function
def fnSelectedNotify(self, pluginText):
Domoticz.Debug("fnSelectedNotify called")
Domoticz.Log("Preparing Notification")
ServerURL = "http://127.0.0.1:8080/json.htm?param=se ... pe=command"
MailSubject = urllib.parse.quote(platform.node() + ":Domoticz Plugin Updates Available for " + self.plugindata[pluginText][2])
MailBody = urllib.parse.quote(self.plugindata[pluginText][2] + " has updates available!!")
MailDetailsURL = "&subject=" + MailSubject + "&body=" + MailBody + "&subsystem=email"
notificationURL = ServerURL + MailDetailsURL
Domoticz.Debug("ConstructedURL is:" + notificationURL)
try:
response = urllib.request.urlopen(notificationURL, timeout = 30).read()
except urllib.error.HTTPError as err1:
Domoticz.Error("HTTP Request error: " + str(err1) + " URL: " + notificationURL)
return
Domoticz.Debug("Notification URL is :" + str(notificationURL))


return None

#
# Parse an int and return None if no int is given
#

def parseIntValue(s):
Domoticz.Debug("parseIntValue called")

try:
return int(s)
except:
return None






def parseFileForSecurityIssues(self, pyfilename, pypluginid):
Domoticz.Debug("parseFileForSecurityIssues called")
secmonitorOnly = False

if Parameters["Mode5"] == 'Monitor':
Domoticz.Log("Plugin Security Scan is enabled")
secmonitorOnly = True


# Open the file
file = open(pyfilename, "r")

ips = {}
#safeStrings = ["['http://schemas.xmlsoap.org/soap/envelope/', 'http://schemas.xmlsoap.org/soap/encoding/']",
# "127.0.0.1",
# "http://schemas.xmlsoap.org/soap/envelope/'",
# "import json",
# "import time",
# "import platform",
# 'import re']

if pypluginid not in self.SecPolUserList:
self.SecPolUserList[pypluginid] = []

lineNum = 1
#Domoticz.Error("self.SecPolUserList[pypluginid]:" + str(self.SecPolUserList[pypluginid]))
for text in file.readlines():
text = text.rstrip()

#Domoticz.Log("'text' is:'" + str(text))
regexFound = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})',text)
paramFound = re.findall(r'<param field=',text)
if ((regexFound) and not (paramFound)):
#regexFound[rex] = regexFound[rex].strip('"]')
#Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
for rex in range(0,len(regexFound)):
if ((str(text).strip() not in self.SecPolUserList["Global"]) and (str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")):
Domoticz.Error("Security Finding(IP):-->" + str(text).strip() + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename)
#Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
ips["IP" + str(lineNum)] = (regexFound[rex], "IP Address")

#rex = 0
#regexFound = re.findall('import', text)

#if regexFound:
#regexFound[rex] = regexFound[rex].strip('"]')
#Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
# for rex in range(0,len(regexFound)):
# if ((str(text).strip() not in self.SecPolUserList["Global"]) and (str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")):
# Domoticz.Error("Security Finding(IMP):-->" + str(text) + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename)
#Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
# ips["IP" + str(lineNum)] = (regexFound[rex], "Import")

#rex = 0
#regexFound = re.findall('subprocess.Popen', text)

#if regexFound:
#regexFound[rex] = regexFound[rex].strip('"]')
#Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
# for rex in range(0,len(regexFound)):
# if ((str(text).strip() not in self.SecPolUserList["Global"]) and (str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")):
# Domoticz.Error("Security Finding(SUB):-->" + str(text) + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename)
#Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
# ips["IP" + str(lineNum)] = (regexFound[rex], "Subprocess")

#rex = 0
#regexFound = re.findall('http?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', text)
#paramFound = re.findall(r'<param field=',text)

#if ((regexFound) and not (paramFound)):
#regexFound[rex] = regexFound[rex].strip('"]')
#Domoticz.Error("Security Finding(IPregex):" + str(regexFound) + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
# for rex in range(0,len(regexFound)):
# if ((str(text).strip() not in self.SecPolUserList[pypluginid]) and (str(text).strip() != "") and (mid(text,0,1) != "#")):
# Domoticz.Error("Security Finding(HTTP):-->" + str(text) + "<-- LINE: " + str(lineNum) + " FILE:" + pyfilename)
#Domoticz.Error("Security Finding(IPr):" + regexFound[rex] + " LINE: " + str(lineNum) + " FILE:" + pyfilename)
# ips["IP" + str(lineNum)] = (regexFound[rex], "HTTP Address")


lineNum = lineNum + 1



file.close()
Domoticz.Debug("IPS Table contents are:" + str(ips))






















global _plugin
_plugin = BasePlugin()

def onStart():
global _plugin
_plugin.onStart()

def onStop():
global _plugin
_plugin.onStop()

def onHeartbeat():
global _plugin
_plugin.onHeartbeat()


# Generic helper functions
def DumpConfigToLog():
for x in Parameters:
if Parameters[x] != "":
Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
Domoticz.Debug("Device count: " + str(len(Devices)))
for x in Devices:
Domoticz.Debug("Device: " + str(x) + " - " + str(Devices[x]))
Domoticz.Debug("Device ID: '" + str(Devices[x].ID) + "'")
Domoticz.Debug("Device Name: '" + Devices[x].Name + "'")
Domoticz.Debug("Device nValue: " + str(Devices[x].nValue))
Domoticz.Debug("Device sValue: '" + Devices[x].sValue + "'")
return


def mid(s, offset, amount):
#Domoticz.Debug("mid called")
return s[offset:offset+amount]




Re: Python Plugin: Python Plugin Manager

Posted: Thursday 23 April 2020 19:13
by ycahome
did you install the pp-manager plugin manually (copy folder) or via github pull?

Re: Python Plugin: Python Plugin Manager

Posted: Thursday 23 April 2020 21:51
by Decyph
yes, after nothing worked anymore i backed up my folder and deleted it, did a new git pull.
Just tried it again and it keeps referring to the wrong cwd.

I must say that also my zigbee2mqtt plugin is acting up and giving errors.

I might have to clean install ubuntu again and try it that way. :cry:

Re: Python Plugin: Python Plugin Manager

Posted: Friday 24 April 2020 11:46
by ycahome
remove pp-manager hardware, delete plugin folder, download pp-manager zip from github and extract folder to your plugins.
That way pp-manager will not auto update. Maybe this is your problem.

NOTE for other users: this is a work around solution to put a different path for plugins instead of auto detect.

Re: Python Plugin: Python Plugin Manager

Posted: Monday 11 May 2020 21:19
by JanJaap
Hi,

I have 2 remarks/questions regarding the plugin manager:
1. I created a plugin to connect to Dyson Pure hot+cool air purifiers/fans, how can I add it? Plugin name "Dyson Pure Link", repo https://github.com/JanJaapKo/DysonPureLink
2. there is the "GoodWe solar inverter via SEMS API" plugin listed on the page. That seems no longer to be supported, perhaps you could add my fork? repo https://github.com/JanJaapKo/domoticz-GoodWeSEMS

Thanks

Re: Python Plugin: Python Plugin Manager

Posted: Monday 11 May 2020 23:12
by ycahome
JanJaap wrote: Monday 11 May 2020 21:19 Hi,

I have 2 remarks/questions regarding the plugin manager:
1. I created a plugin to connect to Dyson Pure hot+cool air purifiers/fans, how can I add it? Plugin name "Dyson Pure Link", repo https://github.com/JanJaapKo/DysonPureLink
2. there is the "GoodWe solar inverter via SEMS API" plugin listed on the page. That seems no longer to be supported, perhaps you could add my fork? repo https://github.com/JanJaapKo/domoticz-GoodWeSEMS

Thanks
Hello,

#1. you can create a pull request on https://github.com/ycahome/pp-manager
#2. you can add your version as additional version (something like "ver JanJaap" or "-fork JJ")

Re: Python Plugin: Python Plugin Manager

Posted: Sunday 17 May 2020 15:51
by JanJaap
Hi,

Thanks for answer (was a bit busy with other stuff, sorry for late reply)
1. PR created (#26).
2. I can't edit the Wiki page. The rights management seems to have changed? Anyway, I added this plugin to the PR .

Re: Python Plugin: Python Plugin Manager

Posted: Wednesday 27 May 2020 18:44
by StasDemydiuk
Thanks to ycahome's great work and basing on the original plugin I've created alternate version with UI (using Domoticz custom page) to easily manage plugins. Hopefully someone else also find it useful. Any feedback is highly welcome

https://github.com/stas-demydiuk/domoti ... ns-manager

Image

Re: Python Plugin: Python Plugin Manager

Posted: Thursday 28 May 2020 17:55
by ycahome
StasDemydiuk wrote: Wednesday 27 May 2020 18:44 Thanks to ycahome's great work and basing on the original plugin I've created alternate version with UI (using Domoticz custom page) to easily manage plugins. Hopefully someone else also find it useful. Any feedback is highly welcome

https://github.com/stas-demydiuk/domoti ... ns-manager

NICE WORK StasDemydiuk

Re: Python Plugin: Python Plugin Manager

Posted: Saturday 25 July 2020 15:15
by MrRikkie
I still see that people struggle with the error message :

Code: Select all

Failed dynamic library load, install the latest libpython3.x library that is available for your platform.
I found my solution in an other post:

Code: Select all

sudo apt-get install python3.7 libpython3.7 python3.7-dev -y

Code: Select all

sudo systemctl restart domoticz.service
This solved my issues with this error message.

Re: Python Plugin: Python Plugin Manager

Posted: Tuesday 20 October 2020 21:05
by Jumper3126
Did anyone got this to work on synology already?
I can install plugin manager and other plugins manually, but cant install plugins via plugin manager.
There are posts from 2 years ago that reported the same. Hopefully someone knows a solution by now. Or should I just give up?

Re: Python Plugin: Python Plugin Manager

Posted: Friday 23 October 2020 14:20
by eddieb
StasDemydiuk wrote: Wednesday 27 May 2020 18:44 Thanks to ycahome's great work and basing on the original plugin I've created alternate version with UI (using Domoticz custom page) to easily manage plugins. Hopefully someone else also find it useful. Any feedback is highly welcome

https://github.com/stas-demydiuk/domoti ... ns-manager
Great work,
and now waiting for owners of other plugins to subscribe their plugins ..

Re: Python Plugin: Python Plugin Manager

Posted: Monday 23 November 2020 17:23
by MLux
I have installed the pp manager as it says on https://www.domoticz.com/wiki/Python_Plugin_Manager but i don't get the plugin manager by the hardware.
What do i wrong?

i'm a newbee :oops:

I found it sorry but's working now :D

Re: Python Plugin: Python Plugin Manager

Posted: Saturday 02 January 2021 12:15
by McMelloW
StasDemydiuk wrote: Wednesday 27 May 2020 18:44 Thanks to ycahome's great work and basing on the original plugin I've created alternate version with UI (using Domoticz custom page) to easily manage plugins. Hopefully someone else also find it useful. Any feedback is highly welcome

https://github.com/stas-demydiuk/domoti ... ns-manager

Image
This is a very nice peace of work. It works OK on my system. Added another plugin an it is visible in the list. Still have to test or you can update it correctly.

Little question: Is there a way to hide/unhide the not installed plugins in the GUI list?

Re: Python Plugin: Python Plugin Manager

Posted: Saturday 02 January 2021 14:07
by madpatrick
StasDemydiuk wrote: Wednesday 27 May 2020 18:44 Thanks to ycahome's great work and basing on the original plugin I've created alternate version with UI (using Domoticz custom page) to easily manage plugins. Hopefully someone else also find it useful. Any feedback is highly welcome

https://github.com/stas-demydiuk/domoti ... ns-manager

Image
Hi,

I'm getting this error after installing:
2021-01-02 13:42:14.733 Status: PluginSystem: Started, Python version '3.6.8'.
2021-01-02 13:42:18.104 Status: Python EventSystem: Initalizing event module.
2021-01-02 13:43:02.984 Status: (Plugins Manager) Started.
2021-01-02 13:43:03.126 Error: (plugins-manager) failed to load 'plugin.py', Python Path used was '/var/domoticz/plugins/plugins-manager/:/usr/lib64/python36.zip:/usr/lib64/python3.6:/usr/lib64/python3.6:/usr/lib64/python3.6/lib-dynload:/usr/local/lib64/python3.6/site-packages:/usr/local/lib/python3.6/site-packages:/usr/lib64/python3.6/site-packages:/usr/lib/python3.6/site-packages'.
2021-01-02 13:43:03.126 Error: (Plugins Manager) Module Import failed, exception: 'FileNotFoundError'
2021-01-02 13:43:03.127 Error: (Plugins Manager) Import detail: File: ./plugins/plugins-manager/plugins.json, Line: -1
2021-01-02 13:43:03.127 Error: (Plugins Manager) Error Line details not available.

Re: Python Plugin: Python Plugin Manager

Posted: Sunday 10 January 2021 12:30
by madpatrick
Changing line 4 in plugins.py makes it able to start the script

Code: Select all

f = open('./plugins/plugins-manager/plugins.json',)
into

Code: Select all

f = open('/var/domoticz/plugins/plugins-manager/plugins.json',)
The custom page is not visible with Machinon Theme

Re: Python Plugin: Python Plugin Manager

Posted: Sunday 10 January 2021 12:43
by madpatrick
DELETE POST

Re: Python Plugin: Python Plugin Manager

Posted: Wednesday 20 January 2021 9:53
by ArtBern
Hello! Are there any options to automate python module installation ? My plugin has dependency on python modules which can be installed via pip3.
It would be nice to install dependencies with plugin manager.

Re: Python Plugin: Python Plugin Manager

Posted: Sunday 07 February 2021 14:08
by brianhunt
StasDemydiuk wrote: Wednesday 27 May 2020 18:44 Thanks to ycahome's great work and basing on the original plugin I've created alternate version with UI (using Domoticz custom page) to easily manage plugins. Hopefully someone else also find it useful. Any feedback is highly welcome

https://github.com/stas-demydiuk/domoti ... ns-manager

Image
Installed this and it does show a 'custom' tab. However if I go to the tab, it stays at 'loading', no plugins are showed.
Any suggestions how to solve this? (have the correct python and libraries). I use the 'Thinktheme', but don't know if that has any influence.
Thanks for your help.