Python Help (Appdaemon & TP-Link SmartPlug HS110)

I’m trying incorportate the utility here: https://github.com/softScheck/tplink-smartplug directly into Appdaemon. I want to obtain the current power usage of the TP-Link smartpluyg. Unfortunately, the socket.send methods of Python 2 vs Python 3 have me stumped. Looking for some string encoding help.

Here is the code in question (mostly directly from the tplink-smartplug project).
The crazy thing is, I swear this actually worked in Appdaemon at one point, but it clearly should not have. The issue is that Python 2 socket.send takes a string and Python 3 socket.send takes bytes. I do not understand how to get the correct encoding and decoding to match what Python 2 does automatically.

The code below (as far as encryption/decryption and socket business works on Python 2), and needs some modifications for Python 3:

import appdaemon.appapi as appapi
import socket
import re

class test(appapi.AppDaemon):

    def initialize(self):
        self.log("running test")
        cmd = '{"emeter":{"get_realtime":{}}}'

        try:
            sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock_tcp.connect(("192.168.0.220", 9999))
            sock_tcp.send(encrypt(cmd))
            data = sock_tcp.recv(2048)
            sock_tcp.close()

            pwr = re.match('(?<=power\":)\d+\.\d+(?=,)', decrypt(data[4:]))
            self.log("pwr = " + str(pwr))

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


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

To get from a string to bytes and back you need encode and decode methods. So assuming you use utf-8 encoding try

            sock_tcp.send(encrypt(cmd).encode())
            data = sock_tcp.recv(2048).decode()

Edit:
Although now I look at the encryption method, I think it is likely to produce invalid utf-8 characters, so encode is likely to fail. I think if you encode as ascii, it will work,

            sock_tcp.send(encrypt(cmd).encode('ascii'))
            data = sock_tcp.recv(2048).decode('ascii')

Thanks for responding.
I did try that; unfortunately, ascii doesn’t work out-of-the-box because it cannot encode all the characters. I also tried:

sock_tcp.send(encrypt(cmd).encode('ascii', 'replace'))

It didn’t work either… checking the .lua file on github for insights, the author apparently replaced unencodable characters with “.”, but the python documentation seems to say that it replaces with “?”.

I wish the python documentation made it more clear how python 2 would encode prior to sending. There must be a way to replicate it in python 3, but it is over my head considering I’m new to python and have no experience with encodings or byte operations.