0

I'm developing a python script for an embedded system that sends data to ThingSpeak.

To do this (and for studing python) I used the thread module and also the ThingSpeak module is used.

Basically my script create 2 threads:

  • One for sending data to ThingSpeak every 10 seconds.
  • One to toggle a LED.

Everything work except the publish on ThingSpeak. Note: the publish on thingSpeak without the thread works.

I get this error: "TypeError: 'str' object does not support item assignment"

Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "thingSpeak.py", line 57, in ThingSpeak_Thread
    response = thingSpeakHandler.update(jsonMessage)
  File "/usr/lib/python2.7/site-packages/thingspeak/thingspeak.py", line 110, in update
    data['api_key'] = self.write_key
TypeError: 'str' object does not support item assignment

I think that this error is related to the addition of threads.

This is my code:

import onionGpio
import time
import thingspeak
import sys
import threading
import random
import thread
import json

# Declare variables
heartBeatDelaySec   = 1.0
heartBeatLedStatus  = 0
heartBeatDisable    = False

thingSpeakDelaySec  = 10

thingSpeakChannel = 98765
thingSpeakWriteKey = '1234556'
thingSpeakReadKey = '123456'


def HeartBeatThread( name, delay, runEvent ):
  global heartBeatLedStatus

  print ("Task " + name + " started")

  while runEvent.is_set():
    blueLed.setValue( heartBeatLedStatus )

    if( heartBeatLedStatus == 0 ):
      heartBeatLedStatus = 1
    else:
      heartBeatLedStatus = 0

    time.sleep(delay)

  # Shut-down Led
  blueLed.setValue( 1 )


def ThingSpeak_Thread( name, delay, thingSpeakChannel, thingSpeakWriteKey, runEvent ):

  thingSpeakHandler = thingspeak.Channel( id=thingSpeakChannel, write_key=thingSpeakWriteKey, fmt='json' )

  while runEvent.is_set():
    temp = random.randint(12, 38)
    rH   = random.randint(30, 68)

    # Build JSON with data
    data = {}
    data['1'] = temp
    data['2'] = rH
    jsonMessage = json.dumps(data)

    print( "Publishing: " + jsonMessage )

    response = thingSpeakHandler.update(jsonMessage)

    time.sleep(delay)


# Led Initialize
blueLed   = onionGpio.OnionGpio(15)
greenLed  = onionGpio.OnionGpio(16)
redLed    = onionGpio.OnionGpio(17)

blueLed.setOutputDirection(1)
greenLed.setOutputDirection(1)
redLed.setOutputDirection(1)

blueLed.setValue(1)
greenLed.setValue(1)
redLed.setValue(1)
print ("GPIO configured")


# Initialize Threads
runEvent = threading.Event()
runEvent.set()

heartBeatThreadHandler = threading.Thread(target = HeartBeatThread, args = ("Heart Beat", heartBeatDelaySec, runEvent))

thingSpeakThreadHandler = threading.Thread(target = ThingSpeak_Thread, args = ("ThingSpeak", thingSpeakDelaySec, thingSpeakChannel, thingSpeakWriteKey, runEvent))

# Start Threads
heartBeatThreadHandler.start()
thingSpeakThreadHandler.start()

try:
  while( True ):
    time.sleep(.01)
except:
  print ("Attempting to close threads. Max wait = " + str(max(heartBeatDelaySec, thingSpeakDelaySec)) + "sec")
  runEvent.clear()
  heartBeatThreadHandler.join()
  thingSpeakThreadHandler.join()
  print ("Threads successfully closed")

Thanks for the help in advance.

Best Regards, Federico

3
  • 2
    A wild guess, but perhaps you're not supposed to manually serialize to JSON, but pass data as dictionary to update(). Commented Aug 2, 2018 at 12:22
  • @IljaEverilä the example provided is "channel.update({1:cpu_pc, 2:mem_avail})" starting from the exmple I think to build the data payload with the json library. I'll try. Thanks Commented Aug 2, 2018 at 12:25
  • @IljaEverilä sorry I made an error. You are right now the script works! Thanks for your help! Commented Aug 2, 2018 at 12:33

1 Answer 1

1

json.dumps() in your function ThingSpeak_Thread returns string (see docs). Then you pass this string to thingSpeakHandler.update() method, but it expects dict. So, remove jsonMessage = json.dumps(data) and pass data to update() instead.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.