Skip to content

ucloud: Add support for a sync mode. #80

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def user_task(client):
# Parse command line args.
parser = argparse.ArgumentParser(description="arduino_iot_cloud.py")
parser.add_argument("-d", "--debug", action="store_true", help="Enable debugging messages")
parser.add_argument("-s", "--sync", action="store_true", help="Run in synchronous mode")
args = parser.parse_args()

# Assume the host has an active Internet connection.
Expand All @@ -60,7 +61,7 @@ def user_task(client):
# Create a client object to connect to the Arduino IoT cloud.
# The most basic authentication method uses a username and password. The username is the device
# ID, and the password is the secret key obtained from the IoT cloud when provisioning a device.
client = ArduinoCloudClient(device_id=DEVICE_ID, username=DEVICE_ID, password=SECRET_KEY)
client = ArduinoCloudClient(device_id=DEVICE_ID, username=DEVICE_ID, password=SECRET_KEY, sync_mode=args.sync)

# Alternatively, the client also supports key and certificate-based authentication. To use this
# mode, set "keyfile" and "certfile", and the CA certificate (if any) in "ssl_params".
Expand All @@ -73,6 +74,7 @@ def user_task(client):
# "keyfile": KEY_PATH, "certfile": CERT_PATH, "cafile": CA_PATH,
# "verify_mode": ssl.CERT_REQUIRED, "server_hostname" : "iot.arduino.cc"
# },
# sync_mode=args.sync,
# )

# Register cloud objects.
Expand Down Expand Up @@ -107,5 +109,11 @@ def user_task(client):
# to client.register().
client.register(Task("user_task", on_run=user_task, interval=1.0))

# Start the Arduino IoT cloud client.
# Start the Arduino IoT cloud client. In synchronous mode, this function returns immediately
# after connecting to the cloud.
client.start()

# In sync mode, start returns after connecting, and the client must be polled periodically.
while True:
client.update()
time.sleep(0.100)
13 changes: 10 additions & 3 deletions examples/micropython_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def wifi_connect():
logging.basicConfig(
datefmt="%H:%M:%S",
format="%(asctime)s.%(msecs)03d %(message)s",
level=logging.INFO,
level=logging.DEBUG,
)

# NOTE: Add networking code here or in boot.py
Expand All @@ -75,7 +75,7 @@ def wifi_connect():
# Create a client object to connect to the Arduino IoT cloud.
# The most basic authentication method uses a username and password. The username is the device
# ID, and the password is the secret key obtained from the IoT cloud when provisioning a device.
client = ArduinoCloudClient(device_id=DEVICE_ID, username=DEVICE_ID, password=SECRET_KEY)
client = ArduinoCloudClient(device_id=DEVICE_ID, username=DEVICE_ID, password=SECRET_KEY, sync_mode=False)

# Alternatively, the client also supports key and certificate-based authentication. To use this
# mode, set "keyfile" and "certfile", and the CA certificate (if any) in "ssl_params".
Expand All @@ -86,6 +86,7 @@ def wifi_connect():
# "keyfile": KEY_PATH, "certfile": CERT_PATH, "cadata": CADATA,
# "verify_mode": ssl.CERT_REQUIRED, "server_hostname" : "iot.arduino.cc"
# },
# sync_mode=False,
# )

# Register cloud objects.
Expand Down Expand Up @@ -133,5 +134,11 @@ def wifi_connect():
except (ImportError, AttributeError):
pass

# Start the Arduino IoT cloud client.
# Start the Arduino IoT cloud client. In synchronous mode, this function returns immediately
# after connecting to the cloud.
client.start()

# In sync mode, start returns after connecting, and the client must be polled periodically.
while True:
client.update()
time.sleep(0.100)
51 changes: 11 additions & 40 deletions src/arduino_iot_cloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

import asyncio
import binascii
from .ucloud import ArduinoCloudClient # noqa
from .ucloud import ArduinoCloudObject
from .ucloud import ArduinoCloudObject as Task # noqa
from .ucloud import timestamp


Expand All @@ -30,33 +30,6 @@
b"8d6444ffe82217304ff2b89aafca8ecf"
)

async def coro(): # noqa
pass


def is_async(obj):
if hasattr(asyncio, "iscoroutinefunction"):
return asyncio.iscoroutinefunction(obj)
else:
return isinstance(obj, type(coro))


class Task(ArduinoCloudObject):
def __init__(self, name, **kwargs):
kwargs.update({("runnable", True)}) # Force task creation.
self.on_run = kwargs.pop("on_run", None)
if not callable(self.on_run):
raise TypeError("Expected a callable object")
super().__init__(name, **kwargs)

async def run(self, aiot):
if is_async(self.on_run):
await self.on_run(aiot)
else:
while True:
self.on_run(aiot)
await asyncio.sleep(self.interval)


class Location(ArduinoCloudObject):
def __init__(self, name, **kwargs):
Expand All @@ -80,24 +53,22 @@ def __init__(self, name, **kwargs):

class Schedule(ArduinoCloudObject):
def __init__(self, name, **kwargs):
kwargs.update({("runnable", True)}) # Force task creation.
kwargs.update({("on_run", self.on_run)})
self.on_active = kwargs.pop("on_active", None)
# Uncomment to allow the schedule to change in runtime.
# kwargs["on_write"] = kwargs.get("on_write", lambda aiot, value: None)
self.active = False
super().__init__(name, keys={"frm", "to", "len", "msk"}, **kwargs)

async def run(self, aiot):
while True:
if self.initialized:
ts = timestamp() + aiot.get("tz_offset", 0)
if ts > self.frm and ts < (self.frm + self.len):
if not self.active and self.on_active is not None:
self.on_active(aiot, self.value)
self.active = True
else:
self.active = False
await asyncio.sleep(self.interval)
def on_run(self, aiot):
if self.initialized:
ts = timestamp() + aiot.get("tz_offset", 0)
if ts > self.frm and ts < (self.frm + self.len):
if not self.active and self.on_active is not None:
self.on_active(aiot, self.value)
self.active = True
else:
self.active = False


class Television(ArduinoCloudObject):
Expand Down
Loading
Loading