如何在2个Differents线程中运行2个Differents循环?

时间:2019-06-14 14:13:17

标签: python python-multithreading azure-iot-hub

我正在使用Azure IoT中心,Python中的Azure IoT SDK和带有温度和湿度传感器的树莓派进行遥测应用程序。

湿度+温度传感器=> Rasperry Pi => Azure IoT中心

在我的第一个实现中,通过azure示例,我使用了一个循环,该循环从温度传感器和湿度传感器收集数据,并每60秒一次将它们发送到Azure IoT中心。

>>> 1 Loop every 60s = Collect data & send data of temperature and humidity

现在我想以不同的频率发送它们,我的意思是: 一个循环将每60秒收集一次温度传感器的数据并将其发送到Azure IoT中心; 而第二个循环将每隔600秒收集一次湿度传感器的数据并将其发送到Azure IoT中心。

>>> 1 Loop every 60s= Collect data & send data of temperature
>>> 2 Loop every 600s= Collect data & send data of humidity 

我认为我需要的工具是多线程,但是我不了解我必须实现哪种库或结构。

这是Azure提供的代码,其中包括一个同时处理温度和湿度的循环。每60秒读取一次数据并发送到Azure。

import random
import time
import sys

# Using the Python Device SDK for IoT Hub:
from iothub_client import IoTHubClient, IoTHubClientError, 
IoTHubTransportProvider, IoTHubClientResult
from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, 
IoTHubError, DeviceMethodReturnValue

# The device connection string to authenticate the device with your IoT hub.
CONNECTION_STRING = "{Your IoT hub device connection string}"

# Using the MQTT protocol.
PROTOCOL = IoTHubTransportProvider.MQTT
MESSAGE_TIMEOUT = 10000

# Define the JSON message to send to IoT Hub.
TEMPERATURE = 20.0
HUMIDITY = 60
MSG_TXT = "{\"temperature\": %.2f,\"humidity\": %.2f}"

def send_confirmation_callback(message, result, user_context):
    print ( "IoT Hub responded to message with status: %s" % (result) )

def iothub_client_init():
    # Create an IoT Hub client
   client = IoTHubClient(CONNECTION_STRING, PROTOCOL)
   return client

def iothub_client_telemetry_sample_run():

    try:
        client = iothub_client_init()
        print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" )

   #******************LOOP*******************************    
   while True:
            # Build the message with simulated telemetry values.
            temperature = TEMPERATURE + (random.random() * 15)
            humidity = HUMIDITY + (random.random() * 20)
            msg_txt_formatted = MSG_TXT % (temperature, humidity)
            message = IoTHubMessage(msg_txt_formatted)

            # Send the message.
            print( "Sending message: %s" % message.get_string() )
            client.send_event_async(message, send_confirmation_callback, None)
            time.sleep(60)

    except IoTHubError as iothub_error:
        print ( "Unexpected error %s from IoTHub" % iothub_error )
        return
    except KeyboardInterrupt:
        print ( "IoTHubClient sample stopped" )

if __name__ == '__main__':
    print ( "IoT Hub Quickstart #1 - Simulated device" )
    print ( "Press Ctrl-C to exit" )
    iothub_client_telemetry_sample_run()

我想使用相同的功能结构,包括两个处理温度和湿度的循环,每60s循环一次,每600s循环一次。

while True:
    # Build the message with simulated telemetry values.
    temperature = TEMPERATURE + (random.random() * 15)
    msg_txt_formatted1 = MSG_TXT1 % (temperature)
    message1 = IoTHubMessage(msg_txt_formatted1)
    # Send the message.
    print( "Sending message: %s" % message1.get_string() )
    client.send_event_async(message1, send_confirmation_callback, None)
    time.sleep(60)

while True:
    # Build the message with simulated telemetry values.
    humidity = HUMIDITY + (random.random() * 20)
    msg_txt_formatted2 = MSG_TXT2 % (humidity)
    message2 = IoTHubMessage(msg_txt_formatted2)
    # Send the message.
    print( "Sending message: %s" % message2.get_string() )
    client.send_event_async(message2, send_confirmation_callback, None)
    time.sleep(600)

我该怎么做?如何使用多线程或其他方法调用这些循环?

2 个答案:

答案 0 :(得分:0)

做类似的事情可能更简单

while True:
    loop_b()
    for _ in range(10):
        loop_a()
        time.sleep(60)

甚至

while True:
    time.sleep(1)
    now = time.time()
    if now % 60 == 0:
        loop_a()
    if now % 600 == 0:
        loop_b()

但是,如果您真的想使用线程,那么:

import threading

class LoopAThread(threading.Thread):
    def run(self):
        loop_a()
class LoopBThread(threading.Thread):
    def run(self):
        loop_b()
...

thread_a = LoopAThread()
thread_b = LoopBThread()
thread_a.start()
thread_b.start()
thread_a.join()
thread_b.join()

答案 1 :(得分:0)

这里有两种相互竞争的方法可供考虑

  1. 根本不用理会线程。像现在一样,每60秒钟休眠一次。跟踪上次发送湿度数据的时间。如果经过600秒,则发送它。否则,请跳过它并入睡60秒钟。像这样:

    # load packages
    library(data.table)
    library(lubridate)
    
    # define a vector evenly spaced each 30 minutes:
    b <- data.table(dates = seq(as.POSIXct("2018-03-25", tz = "UTC"), 
                                as.POSIXct("2018-03-26", tz = "UTC"), 
                                by = "30 min"))
    
    # reproduce data
    dt <- data.table(detect_date = as.character(c("25/03/2018 00:09", "25/03/2018 01:17", "25/03/2016 14:37", "25/03/2016 23:43")), 
                     Station = c("SS01", "SS03", "SS04", "SS04"), 
                     Individual = c("A", "B", "C", "B"))
    
    # convert detect_date to date format
    dt[, detect_date := dmy_hm(detect_date)]
    
    # make a join
    dt[, .(Location = Station, Individual), by = .(dates = floor_date(detect_date, "30 minutes"))][b, on = "dates"]
    
  2. from datetime import datetime, timedelta def iothub_client_telemetry_sample_run(): last_humidity_run = None humidity_period = timedelta(seconds=600) client = iothub_client_init() while True: now = datetime.now() send_temperature_data(client) if not last_humidity_run or now - last_humidity_run >= humidity_period: send_humidity_data(client) last_humidity_run = now time.sleep(60) 重命名为iothub_client_telemetry_sample_run或类似的名称。创建一个单独的功能,看起来就像湿度一样。从程序的主要功能中产生两个线程。将它们设置为守护程序模式,以便在用户退出时关闭

    temperature_thread_func

注释:

  • 如果您决定使用线程,请考虑使用 event 干净地终止它们。
  • from threading import Thread def temperature_thread_func(): client = iothub_client_init() while True: send_temperature_data(client) time.sleep(60) def humidity_thread_func(): client = iothub_client_init() while True: send_humidity_data(client) time.sleep(600) if __name__ == '__main__': temp_thread = Thread(target=temperature_thread_func) temp_thread.daemon = True humidity_thread = Thread(target=humidity_thread_func) humidity_thread.daemon = True input('Polling for data. Press a key to exit') 不是一种精确的保留方法 时间。如果样本需要,您可能需要不同的计时机制 在精确的时刻拍摄。