Unicode temperatures

Posted on
Thu Apr 25, 2019 3:22 pm
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Unicode temperatures

Code: Select all
dev.updateStateOnServer(key='sensorValue', value = baseValue, decimalPlaces=1, uiValue=str(baseValue) + u' °C')

dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u' °C')

dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u"\u00b0F")
The first line above is shamelessly plagiarised from @FlyingDiver's Masquerade plugin - and seemingly works.

The second line is my version - which throws the following error:

The third line is @CliveS's suggested fix - which also throws the following error:

Code: Select all
SyntaxError: ("(unicode error) 'utf8' codec can't decode byte 0xb0 in position 0: invalid start byte",
      ('plugin.py', 109, None, 'dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u" \xb0C")\n'))
What am I doing wrong? The ° character is typed in on Windows using Alt+0176 which inserts the unicode utf-8 symbol that you see.

I've played with ' and with " in the commands in case it makes a difference, but I definitely don't have Smart Quotes involved.

Peter

Posted on
Thu Apr 25, 2019 4:00 pm
DaveL17 offline
User avatar
Posts: 6753
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Unicode temperatures

Hey Peter. Unicode is a pain.

Since moving everything over to the .format() specifier, I (knock on wood) haven't seen any Unicode errors. I do the following (including the shebang line):

Code: Select all
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

u"{0}{1}".format('thing 1', 'thing 2')


In the rare circumstances where I've come across this error in the past, I've had to encode/decode the offending bit 'manually'. Try:
Code: Select all
dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u' °C'.decode('utf-8'))

I can't test your code; when I run it in a shell, it runs without error. I told you Unicode was a pain. :D

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

[My Plugins] - [My Forums]

Posted on
Thu Apr 25, 2019 4:06 pm
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Unicode temperatures

DaveL17 wrote:
Hey Peter. Unicode is a pain.

Since moving everything over to the .format() specifier, I (knock on wood) haven't seen any Unicode errors.

Tell me about it!

Learning the .format() specifier is on the list with using the new log level debugging / plugin error logs introduced in about Indigo v4, followed by seeing what these PyBug thingies are all about.

Never used an attached debugger in my life, other than where it’s in the IDE such as Powershell and VB.Net (and other Visual Studio languages).


Sent from my iPhone using Tapatalk Pro

Posted on
Thu Apr 25, 2019 5:33 pm
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Unicode temperatures

Here's my advice to anyone doing Python with Indigo:

  1. Always use the format() method to format strings. It just handles pretty much any object for you automatically.
  2. Always use u"stuff" (or u'stuff') on embedded strings. I'm not very good at this rule either, but seriously it'll save you a lot of headaches eventually.
  3. Always try unicode() first before str(). Another one I'm not super consistent with, but in most cases unicode() is your best bet.

The problem with your original one was you were trying to use "+" on a str (non-unicode string) and a unicode. I think this version would have worked:

Code: Select all
dev.updateStateOnServer("displayState", str(varValue), uiValue=unicode(varValue) + u' °C')


Although I will point out that if varValue came directly from an Indigo variable then it's already unicode so casting it is unnecessary.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Thu Apr 25, 2019 7:18 pm
DaveL17 offline
User avatar
Posts: 6753
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Unicode temperatures

This is a nice explanation that I highly recommend.

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

[My Plugins] - [My Forums]

Posted on
Fri Apr 26, 2019 1:16 am
rhanson offline
Posts: 192
Joined: Apr 30, 2013

Re: Unicode temperatures

Reason #712 to move to Python3 sooner than later...

Posted on
Fri Apr 26, 2019 12:38 pm
CliveS offline
Posts: 770
Joined: Jan 10, 2016
Location: Medomsley, County Durham, UK

Re: Unicode temperatures

I have been playing with this and found the following

I added these lines
Code: Select all
            elif (icon == 'TempC'):
#                dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + degreeC + "1")
#                dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u'\u00b0C'+ "2")
                 dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u'°C' + "3")
#                dev.updateStateOnServer("displayState", str(varValue), uiValue=str(varValue) + u'°C' + "4")
                 dev.updateStateImageOnServer(indigo.kStateImageSel.TemperatureSensorOn)

and rem'ed out each line in turn and reloaded and got
Code: Select all
   Reloading plugin "Variable Device 1.0.2"
   Stopping plugin "Variable Device 1.0.2" (pid 15697)
   Variable Device                 Stop monitoring variable: Average_Outside_Temp
   Stopped plugin "Variable Device 1.0.2"
   Starting plugin "Variable Device 1.0.2" (pid 15830)
   Started plugin "Variable Device 1.0.2"
   Variable Device                 Monitoring variable: Average_Outside_Temp

except for the third line which is the original (4th line is Masquerade version which is fine)

Code: Select all
   Reloading plugin "Variable Device 1.0.2"
   Stopping plugin "Variable Device 1.0.2" (pid 15380)
   Variable Device                 Stop monitoring variable: Average_Outside_Temp
   Stopped plugin "Variable Device 1.0.2"
   Starting plugin "Variable Device 1.0.2" (pid 15441)
   Started plugin "Variable Device 1.0.2"
   Variable Device                 Monitoring variable: Average_Outside_Temp
   Variable Device Error           exception in deviceStartComm(new device 1): bad operand type for unary +: 'unicode'


Following Jay's suggestion I then changed line 3 to

Code: Select all
               dev.updateStateOnServer("displayState", str(varValue), uiValue=unicode(varValue) + u'°C' + "3")

and now just like the rest no errors! :)

CliveS

Indigo 2023.2.0 : macOS Ventura 13.6.3 : Mac Mini M2 : 8‑core CPU and 10‑core GPU : 8 GB : 256GB SSD
----------------------------------------------------------------------------------
The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer

Posted on
Fri Apr 26, 2019 1:52 pm
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Unicode temperatures

Interestingly, this should be failing:

Code: Select all
dev.updateStateOnServer("displayState", str(varValue), uiValue=unicode(varValue) + u'°C' + "3")


Because you're trying to concatenate a unicode + unicode + str. I guess since "3" could easily be cast to unicode it works. I would highly recommend dumping string concatenation in favor of the format() method however.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Fri Apr 26, 2019 2:26 pm
CliveS offline
Posts: 770
Joined: Jan 10, 2016
Location: Medomsley, County Durham, UK

Re: Unicode temperatures

jay (support) wrote:
Interestingly, this should be failing:

Code: Select all
dev.updateStateOnServer("displayState", str(varValue), uiValue=unicode(varValue) + u'°C' + "3")


Because you're trying to concatenate a unicode + unicode + str. I guess since "3" could easily be cast to unicode it works. I would highly recommend dumping string concatenation in favor of the format() method however.


The + "3" was added to see what line was active on reboot, but yes I can see what you mean.

As for going to .format I have started but the learning curve just gets steeper.

CliveS

Indigo 2023.2.0 : macOS Ventura 13.6.3 : Mac Mini M2 : 8‑core CPU and 10‑core GPU : 8 GB : 256GB SSD
----------------------------------------------------------------------------------
The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer

Posted on
Sat Apr 27, 2019 3:24 pm
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Unicode temperatures

Finally settled on:

Code: Select all
dev.updateStateOnServer("displayState", str(varValue), uiValue=u'{} {}'.format(varValue, u"\u00b0C"))
If I tried °C even in the .format() bit, it still errored out.

Dave, it turns out I already have those shebang lines as my first plugin was cloned from the Indigo SDKs, then all my plugins since have been cloned from whichever of my plugins had the nearest style to what I was writing next, ie this one is cloned from ZWave Watcher as it's simply watching variables instead of devices.

Jay, when I get an exception in deviceStartComm about the ascii encoding bytes etc - why does this just report as a single line error, rather than a multi-line trace detailing which .py file, function and line no and character the error occurred on? I was forever going through putting debug lines in between every line to work out which point it was erroring.

Variable Device Debug Updating displayState: 20.5
Variable Device Error exception in deviceStartComm(PAH States): 'ascii' codec can't decode byte 0xb0 in position 0: ordinal not in range(128)
Variable Device Debug Update received: MotionStudyPIROn: 2019-04-27 21:54:41

Posted on
Mon Apr 29, 2019 9:57 am
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Unicode temperatures

Something else that looks wonky to me is this:

Code: Select all
deviceStartComm(PAH States)


Not sure where PAH States is coming from...

Anyway, I just downloaded the 1.0.3 version of your plugin and changed these lines in the startup method:

Code: Select all
      self.uiValue["TempF"] = u" °F"
      self.uiValue["TempC"] = u" °C"


and it worked fine...

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Apr 29, 2019 10:02 am
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Unicode temperatures

PAH States is the name of the device.

I’m thinking Windows vs Mac is upsetting the typing of the degree symbol (which I can’t type on iOS!) - if you and @FD type it in a .py file it works but if I type it on Windows it breaks.


Sent from my iPhone using Tapatalk Pro

Posted on
Mon Apr 29, 2019 10:23 am
jay (support) offline
Site Admin
User avatar
Posts: 18220
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Unicode temperatures

howartp wrote:
PAH States is the name of the device.

I’m thinking Windows vs Mac is upsetting the typing of the degree symbol (which I can’t type on iOS!) - if you and @FD type it in a .py file it works but if I type it on Windows it breaks.


That's what you get for running Windoze... :lol:

BTW, press and hold the zero key on an iOS keyboard and you'll get a popup with the option to insert the degree symbol. You're welcome!

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Mon Apr 29, 2019 12:37 pm
howartp offline
Posts: 4559
Joined: Jan 09, 2014
Location: West Yorkshire, UK

Re: Unicode temperatures

9°°°°@&$);:/-\–—•…,¿¡’

Oooh!


Sent from my iPhone using Tapatalk Pro

Posted on
Thu Jul 30, 2020 6:06 pm
hannt offline
User avatar
Posts: 84
Joined: Jul 08, 2011
Location: TN USA

Re: Unicode temperatures

DaveL17 wrote:
Hey Peter. Unicode is a pain.

That's an understatement!

I'm working on a custom plugin that also uses temperatures and would like to use the degree symbol. The user might enter this in a textfield within the device configuration UI using <shift-option-8>. The problem I was having was when I print the valuesDict to the log file for debugging. Here's the original code:

Code: Select all
def validateDeviceConfigUi(self, valuesDict, typeId, devId):
      self.logger.debug(u"validateDeviceConfigUi()\n{}".format(str(valuesDict).encode('utf-8')))
I was getting the error

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 1935: ordinal not in range(128)

While creating this forum post, I tried a few more things and after reading Jay's post, this is what finally worked. It's so simple:
Code: Select all
def validateDeviceConfigUi(self, valuesDict, typeId, devId):
      self.logger.debug(u"validateDeviceConfigUi()\n{}".format(valuesDict))
And what's even better... An easy way to see properties and states of a dev is to print the dev from the command shell.

Code: Select all
>>> dev = indigo.devices[865221023]
>>> print dev
However, the same error can show up when printed this way. The easy way to fix it is:

Code: Select all
>>> dev = indigo.devices[865221023]
>>> print unicode(dev)
Spent way too much time figuring this one out so I thought I'd share.

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 5 guests