Assistance with Python 3 Script Errors

Posted on
Thu May 12, 2022 12:32 pm
sumocomputers offline
Posts: 267
Joined: Jun 23, 2008

Assistance with Python 3 Script Errors

I have some scripts that were working on Python 2, but now that I am on Python 3 with the latest Indigo upgrade, I am getting this error on a script, and after some Googling, I am not sure how to solve it:

Code: Select all
Script Error schedule "TPLink 04 Check Power State" embedded script error:
Script Error a bytes-like object is required, not 'str'
Script Error Exception Traceback (most recent call shown last):

embedded script, line 59, at top level
TypeError: a bytes-like object is required, not 'str'


Here is the Script in question:

Code: Select all
#!/usr/bin/env python
#
# TP-Link Wi-Fi Smart Plug Protocol Client
# For use with TP-Link HS-100 or HS-110

# by Lubomir Stroetmann
# Copyright 2016 softScheck GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
import socket

import indigo
import json

# Encryption and Decryption of TP-Link Smart Home Protocol
# XOR Autokey Cipher with starting key = 171
def encrypt(string):
   key = 171
   result = "\0\0\0\0"
   for i in string:
      a = key ^ ord(i)
      key = a
      result += chr(a)
   return result

def decrypt(string):
   key = 171
   result = ""
   for i in string:
      a = key ^ ord(i)
      key = ord(i)
      result += chr(a)
   return result


# Set target IP, port and command to send

ip = '192.168.20.144'
port = 9999
cmd = '{"system":{"get_sysinfo":{}}}'
var = indigo.variables[981436479]           #  Change this to the actual ID of your variable

# Send command and receive reply
try:
    sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock_tcp.connect((ip, port))
    sock_tcp.send(encrypt(cmd))
    data = sock_tcp.recv(2048)
    sock_tcp.close()
   
#   indigo.server.log("Sent:     ", cmd)
#   indigo.server.log("Received: ", decrypt(data[4:]))
   
    jsonData = json.loads(decrypt(data[4:]))
    var.value = unicode( jsonData["system"]["get_sysinfo"]["relay_state"])
    var.replaceOnServer()

except socket.error:
    indigo.server.error("Cound not connect to host " + ip + ":" + str(port))

Posted on
Thu May 12, 2022 1:40 pm
jay (support) offline
Site Admin
User avatar
Posts: 18219
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Assistance with Python 3 Script Errors

This was one of the big changes between Python 2 and 3 - low-level communication libraries like sockets started using bytes rather than strings since strings in Python 3 are now unicode (multibyte).

I would recommend that you look into switching to the TP-Link plugin rather than using this script because updating the script is going to be non-trivial. The plugin hasn't been updated yet, and I'm not sure that discovery is working, but I can confirm it still works with 2022.1. We'll be working with other plugin developers to get their plugins updated for 2022.2 later this year.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Thu May 12, 2022 2:31 pm
sumocomputers offline
Posts: 267
Joined: Jun 23, 2008

Re: Assistance with Python 3 Script Errors

I only have one other fairly simple script which I do need for my TED energy monitor. I had to do this a few years back when the plugin gave me issues, and I am getting the same error.

Looks like it errors on the line starting with:

Code: Select all
now = response.content.split('\n')[1]


Here is the script:

Code: Select all
# -*- coding: utf-8 -*-
import indigo
import requests
import math
import urllib
import re
import xml.etree.ElementTree as ET

#TED Dashboard GET
response = requests.get('http://192.168.20.90/api/DashData.xml')
requestURL = 'http://192.168.20.90/api/DashData.xml'
root = ET.fromstring(response.content)

now = response.content.split('\n')[1]
now = re.sub("<Now>","",now)

energyNow = float(now.split('<')[0])
energyNow = energyNow/1000

indigo.variable.updateValue(108813449, u"{0:.3f}".format(energyNow))

Posted on
Thu May 12, 2022 3:39 pm
jay (support) offline
Site Admin
User avatar
Posts: 18219
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Assistance with Python 3 Script Errors

Can you post the XML that's returned from the URL so we can try it out? Also, what error are you seeing?

[MODERATOR NOTE]: moved to the new forum for Python 3 conversion help

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Thu May 12, 2022 3:42 pm
sumocomputers offline
Posts: 267
Joined: Jun 23, 2008

Re: Assistance with Python 3 Script Errors

I was able to change this:
Code: Select all
now = response.content.split('\n')[1]

To this:
Code: Select all
now = response.content.decode("utf-8").split('\n')[1]

That seems to have worked. Might help other non-developers like me.

Posted on
Fri May 13, 2022 10:38 am
jay (support) offline
Site Admin
User avatar
Posts: 18219
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Assistance with Python 3 Script Errors

Yes - responses from network communication are usually bytes (byte string/array), so you have to decode them into their correct representation, which is usually (but not always) UTF-8, which will result in a Python str (string) object. You can then do all the typical string processing you need to do.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Fri May 13, 2022 10:40 pm
mclass offline
Posts: 314
Joined: May 13, 2015
Location: Melbourne, Australia

Re: Assistance with Python 3 Script Errors

Hi,

I have the opposite issue - how to send bytes rather than strings in the following script (and a variety of other similar scripts used to control RollEase blinds:

Code: Select all
import socket
HOST = '10.10.XX.XXX'  # hub address
PORT = ZZZZ             # port
TARGET_ID = 'ZBY'
COMMAND = 'o'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST,PORT))
s.sendall('!' + TARGET_ID + COMMAND + ';')
data = s.recv(1024)

#   print('Received', data)
indigo.server.log(data,'Received from blind ID ' + TARGET_ID + ': ')


The following error is reported in the line "s.sendall('!' + TARGET_ID + COMMAND + ';')".
Code: Select all
Script Error                    action group "Close Study Blind" script error in file RA Study Close_Rev00.py:
   Script Error                    a bytes-like object is required, not 'str'
   Script Error                    Exception Traceback (most recent call shown last):

     RA Study Close_Rev00.py, line 21, at top level
TypeError: a bytes-like object is required, not 'str'


The characters "!" and ";" are required by the RollEase API, and presumably I need to change the TARGET_ID and COMMAND variables to "byte-like" objects - but how??

Thanks in advance for any assistance!

mclass

Posted on
Sat May 14, 2022 1:57 am
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Assistance with Python 3 Script Errors

Code: Select all
TARGET_ID = “ZBY”.encode(‘UTF-8’)



Sent from my iPhone using Tapatalk Pro

Posted on
Sat May 14, 2022 8:46 pm
mclass offline
Posts: 314
Joined: May 13, 2015
Location: Melbourne, Australia

Re: Assistance with Python 3 Script Errors

Simples ....!!

With thanks.

For info of others, I did have to use
Code: Select all
TARGET_ID = “ZBY”.encode("utf-8")

for some reason.

Again many thanks for the prompt response - and solution!!

Mclass

Posted on
Sun May 15, 2022 10:53 am
jay (support) offline
Site Admin
User avatar
Posts: 18219
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Assistance with Python 3 Script Errors

[MODERATOR NOTE]: moved to the Python 3 conversion forum.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 1 guest