Late to the party: Need help converting plugin to PY3

Posted on
Sun Oct 22, 2023 5:35 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Late to the party: Need help converting plugin to PY3

Several years ago with much help from Jay, I adapted an old version of the NOAA weather plugin to read an XML file. The file is generated and posted to a local network site by a hardware device called "Web Energy Logger (WEL)) that converts one-wire sensor HVAC data and updates the file periodically. The plugin worked fine until (of course) I updated Indigo to 2023.1.

I have attempted to convert the code to PY3. The plugin runs, I can create a device in Indigo, and the device states from the plugin's devices.xml file are shown in the main Indigo window. However, no data is updated.

I have inserted debug log points to see what modules are being called, and the only ones that are logged are "Startup" and "Concurrent Thread." Notably, the self.deviceStartComm and self.Update routines do not execute. I have tried to force self.deviceStartComm in startup(self) without success.
Also, in the indigo window, the device's "Comm Enabled" block is not checked even though "Enable Indigo Communication" is selected in the device edit window.

I've obviously overlooked something simple, but have been pounding on this for a couple of days with no real progress. Any help would be much appreciated.

plugin.py:
Code: Select all
################################################################################
# Imports
################################################################################
import urllib.request, urllib.error, urllib.parse
import logging
from xml.dom.minidom import parseString
################################################################################
# Globals
################################################################################
theUrl = "http://10.1.0.30:5150/data.xml"
fields = {"dataDate":'Date',"dataTime":'Time',"TEST":'test',"propHeat":'PropHeating',"outdoorTemp":'OutdoorT',"stage2":'HP_ComprHi',"cooling":'HP_Cool1S',"heating":'HP_Heat1S',"defrost":'HP_Defrost',"vaporTemp":'HP_VaporT',"liquidTemp":'HP_LiquidT',"supplyTemp":'HP_SupplyT',"downstairsReturnTemp":'HP_ReturnDnT',"upstairsReturnTemp":'HP_ReturnUpT',"hotWaterTemp":'Water_Hot',"coldWaterTemp":'Water_Cold',"returnDeltaT":'AirRetDeltaT'}

################################################################################
class Plugin(indigo.PluginBase):
   ########################################
   # Class properties
   ########################################
   
   ########################################
   def __init__(self, plugin_id, plugin_display_name, plugin_version, plugin_prefs):
#      """ Standard Plugin Initialization Method """
      super().__init__(plugin_id, plugin_display_name, plugin_version, plugin_prefs)

      log_format = '%(asctime)s.%(msecs)03d\t%(levelname)-10s\t%(name)s.%(funcName)-28s %(message)s'
      self.plugin_file_handler.setFormatter(logging.Formatter(log_format, datefmt='%Y-%m-%d %H:%M:%S'))
      self.debug = plugin_prefs.get("showDebugInfo", False)
      self.device_list = []
   
   ########################################
   def __del__(self):
      indigo.PluginBase.__del__(self)
   
   ########################################
   
   ########################################
   def deviceStartComm(self, device):
      self.logger.debug(u"deviceStartComm called")
      try:
         self.logger.debug(u"Starting device: {device.name}")
         if device.id not in self.device_list:
            self.update(device)
            self.device_list.append(device.id)
      except requests.exceptions.ConnectionError:
         self.logger.warning(u"Unable to connect to Indigo WEL device.")
         ########################################

   ########################################
   def deviceStopComm(self, device):
      self.logger.debug(u"Stopping device: " + device.name)
      if device.id in self.device_list:
         self.device_list.remove(device.id)
         
   ########################################
   
   ########################################
   def startup(self):
      self.logger.debug(u"Startup called")
      for device_id in self.device_list:
         self.deviceStartComm(self, indigo.devices[device.id])
   
   ########################################
   def runConcurrentThread(self):
      self.logger.debug(u"Starting concurrent thread")
      self.sleep(10)
      try:
         while True:
            self.sleep(10)
#            self.logger.debug(u"Line 71")
            for device_id in self.device_list:
               # call the update method with the device instance
               self.logger.debug(u"Calling self update for: {device.name}")
               self.update(indigo.devices[device_id], force_update=True)
      except self.StopThread:
         self.logger.debug(u"Exception stopped thread")
         pass
   
   ########################################
   ########################################
   def update(self,device):
      self.logger.debug(u"Updating device: " + device.name)
      # download the file
      try:
         f = urllib.request.urlopen(theUrl)
      except urllib.error.HTTPError as e:
         self.logger.error(u"Error getting data: %s" % (device.pluginProps["address"], str(e)))
         return
      theXml = f.read()
      theDocTree = parseString(theXml)
      for node in theDocTree.getElementsByTagName("Device"):
         for state,fieldName in list(fields.items()):
            name = node.getAttribute("Name")
            value = node.getAttribute("Value")
            if name == fieldName:
               newValue = value
               if (fieldName == "OutdoorT")|(fieldName=="HP_VaporT")|(fieldName=="HP_LiquidT")|(fieldName=="HP_SupplyT")|(fieldName=="HP_ReturnDnT")|(fieldName=="HP_ReturnUpT")|(fieldName=="Water_Hot")|(fieldName=="Water_Cold")|(fieldName=="AirRetDeltaT"):
                  newValue = str(round(float(value),1))
               if value == "0.000000":
                  newValue = "0"
               if value == "1.000000":
                  newValue = "1"
               self.updateDeviceState(device, state, newValue)

   ########################################
   def updateDeviceState(self,device,state,newValue):
      if state not in device.states:
         device.stateListOrDisplayStateIdChanged()
      if (newValue != device.states[state]):
         device.updateStateOnServer(key=state, value=newValue)

   ########################################


Devices.xml:
Code: Select all
<?xml version="1.0"?>
<Devices>
   <!-- Define some devices -->
   <Device type="custom" id="welData">
      <Name>WEL Data</Name>
      <ConfigUI>
      </ConfigUI>
      <States>
         <State id="dataDate">
            <ValueType>String</ValueType>
            <TriggerLabel>Data Date</TriggerLabel>
            <ControlPageLabel>Data Date</ControlPageLabel>
         </State>         
         <State id="dataTime">
            <ValueType>String</ValueType>
            <TriggerLabel>Data Time</TriggerLabel>
            <ControlPageLabel>Data Time</ControlPageLabel>
         </State>
         <State id="heating">
            <ValueType>Boolean</ValueType>
            <TriggerLabel>Heat</TriggerLabel>
            <ControlPageLabel>Heat</ControlPageLabel>
         </State>
         <State id="cooling">
            <ValueType>Boolean</ValueType>
            <TriggerLabel>Cool</TriggerLabel>
            <ControlPageLabel>Cool</ControlPageLabel>
         </State>
         <State id="defrost">
            <ValueType>Boolean</ValueType>
            <TriggerLabel>Defrost</TriggerLabel>
            <ControlPageLabel>Defrost</ControlPageLabel>
         </State>
         <State id="stage2">
            <ValueType>Boolean</ValueType>
            <TriggerLabel>Second Stage H/C</TriggerLabel>
            <ControlPageLabel>Second Stage H/C</ControlPageLabel>
         </State>
         <State id="propHeat">
            <ValueType>Boolean</ValueType>
            <TriggerLabel>Propane Heat is On</TriggerLabel>
            <ControlPageLabel>Propane Heating</ControlPageLabel>
         </State>
         <State id="vaporTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Heat Pump Vapor Temp °F</TriggerLabel>
            <ControlPageLabel>Heat Pump Vapor Temp °F</ControlPageLabel>
         </State>
         <State id="liquidTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Heat Pump Liquid Temp °F</TriggerLabel>
            <ControlPageLabel>Heat Pump Liquid Temp °F</ControlPageLabel>
         </State>
         <State id="outdoorTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Outdoor Temp °F</TriggerLabel>
            <ControlPageLabel>Outdoor Temp °F</ControlPageLabel>
         </State>
         <State id="supplyTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Supply Temp °F</TriggerLabel>
            <ControlPageLabel>Supply Temp °F</ControlPageLabel>
         </State>
         <State id="upstairsReturnTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Upstairs Return Temp °F</TriggerLabel>
            <ControlPageLabel>Upstairs Return Temp °F</ControlPageLabel>
         </State>
         <State id="downstairsReturnTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Downstairs Return Temp °F</TriggerLabel>
            <ControlPageLabel>Downstairs Return Temp °F</ControlPageLabel>
         </State>
         <State id="hotWaterTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Hot Water Temp °F</TriggerLabel>
            <ControlPageLabel>Hot Water Temp °F</ControlPageLabel>
         </State>
         <State id="returnDeltaT">
            <ValueType>Number</ValueType>
            <TriggerLabel>Return Temp Difference °F</TriggerLabel>
            <ControlPageLabel>Return Temp Difference °F</ControlPageLabel>
         </State>
         <State id="coldWaterTemp">
            <ValueType>Number</ValueType>
            <TriggerLabel>Cold Water Temp °F</TriggerLabel>
            <ControlPageLabel>Cold Water Temp °F</ControlPageLabel>
         </State>
      </States>
   </Device>
</Devices>


Log of plugin running (no other entries):
Code: Select all
   Started plugin "WEL Data New 1.0.1"
   WEL Data New Debug              Startup called
   WEL Data New Debug              Starting concurrent thread

Posted on
Sun Oct 22, 2023 6:59 pm
FlyingDiver offline
User avatar
Posts: 7241
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Late to the party: Need help converting plugin to PY3

In the "General Settings" dialog, "Plugins" tab, enable the "Enable Debug Menus" option, Then use the "Reload in Interactive Shell" menu item, which will open a Terminal window. Post what you're getting there.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Oct 22, 2023 7:00 pm
FlyingDiver offline
User avatar
Posts: 7241
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Late to the party: Need help converting plugin to PY3

Also, go through all the code and remove the 'u' from the strings (u"string value").

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Oct 22, 2023 7:15 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Re: Late to the party: Need help converting plugin to PY3

Sorry, didn’t mean to do that as pm.

In the "General Settings" dialog, "Plugins" tab, enable the "Enable Debug Menus" option, Then use the "Reload in Interactive Shell" menu item, which will open a Terminal window. Post what you're getting there.

I see that menu item for some, but not all, plugins; it’s not there for the one of interest. Do I need to do something in the code to enabl it?
Last edited by BillC on Sun Oct 22, 2023 7:20 pm, edited 1 time in total.

Posted on
Sun Oct 22, 2023 7:17 pm
FlyingDiver offline
User avatar
Posts: 7241
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Late to the party: Need help converting plugin to PY3

That's strange. It's in all of mine.

Did you update the Info.plist to the correct ServerApiVersion? Should be 3.0.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Oct 22, 2023 7:24 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Re: Late to the party: Need help converting plugin to PY3

Yes.

It’s also not available in the NOAA weather plugin. I’ll look at some of the other info.plist files and see if I can spot anything.

Posted on
Sun Oct 22, 2023 7:25 pm
FlyingDiver offline
User avatar
Posts: 7241
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Late to the party: Need help converting plugin to PY3

You are running the client on the Indigo server machine, right?

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Oct 22, 2023 7:51 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Re: Late to the party: Need help converting plugin to PY3

Can’t determine how to activate that menu item. It’s not available for the following plugins I have installed:
NOAA weather
Airfoil Pro
Email+
Timers and pesters

?????

Posted on
Sun Oct 22, 2023 7:52 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Re: Late to the party: Need help converting plugin to PY3

You are running the client on the Indigo server machine, right?


Yes.

Posted on
Sun Oct 22, 2023 7:54 pm
FlyingDiver offline
User avatar
Posts: 7241
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Late to the party: Need help converting plugin to PY3

But it is present for other plugins?

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Oct 22, 2023 7:58 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Re: Late to the party: Need help converting plugin to PY3

Some but not all. NOT for:

NOAA weather
Airfoil Pro
Email+
Timers and pesters

Posted on
Sun Oct 22, 2023 7:59 pm
FlyingDiver offline
User avatar
Posts: 7241
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Late to the party: Need help converting plugin to PY3

I have no clue. Maybe Matt or Jay have an idea about that.

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Sun Oct 22, 2023 8:01 pm
BillC offline
Posts: 237
Joined: Mar 09, 2008

Re: Late to the party: Need help converting plugin to PY3

Thanks for your help, Joe. Calling it a night, will try again tomorrow. Appreciate your assistance.

Posted on
Sun Oct 22, 2023 11:48 pm
GlennNZ offline
User avatar
Posts: 1578
Joined: Dec 07, 2014
Location: Central Coast, Australia

Re: Late to the party: Need help converting plugin to PY3

Hi,

Can I put in a plug for the excellent GhostXML plugin?

Essentially appears to be designed for this purpose - although now does a lot more.

https://www.indigodomo.com/pluginstore/38/

Should take your xml url directly and generate all device states that it can get from the xml.

Glenn


Sent from my iPad using Tapatalk

Posted on
Mon Oct 23, 2023 3:19 am
DaveL17 offline
User avatar
Posts: 6781
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Late to the party: Need help converting plugin to PY3

BillC wrote:
Can’t determine how to activate that menu item. It’s not available for the following plugins I have installed:
NOAA weather
[snip]

Just to be sure that everyone is on the same page:

1. Indigo General Settings --> General Settings... --> Plugins --> Enable debugging menus {is checked]
2. Plugins --> NOAA Weather --> Reload in Interactive Shell

The option in number 2 is not present? That's really weird.

Screenshot 2023-10-23 at 4.12.14 AM-2.png
Screenshot 2023-10-23 at 4.12.14 AM-2.png (133.92 KiB) Viewed 1845 times

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Who is online

Users browsing this forum: No registered users and 1 guest