Skip to content

Commit

Permalink
Merge pull request #15 from brainelectronics/feature/support-rtc
Browse files Browse the repository at this point in the history
Add support for RTC
  • Loading branch information
brainelectronics authored Jul 30, 2022
2 parents d9bb9f0 + 8898ae9 commit 0c28b07
Show file tree
Hide file tree
Showing 5 changed files with 342 additions and 2 deletions.
11 changes: 10 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$"
-->

## Released
## [0.12.0] - 2022-07-30
### Added
- Support `NexRtc` usage with [`nextion_rtc`](nextion/nextion_rtc.py)

### Fixed
- Add missing documentation for [upload example](examples/upload/main.py) to
[examples README](examples/)

## [0.11.0] - 2022-07-30
### Added
- Support `NexUpload` usage with [`nextion_upload`](nextion/nextion_upload.py)
Expand Down Expand Up @@ -156,8 +164,9 @@ r"^\#\# \[\d{1,}[.]\d{1,}[.]\d{1,}\] \- \d{4}\-\d{2}-\d{2}$"
- [Example HMI file](examples/everything.HMI) to be used for all examples

<!-- Links -->
[Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.11.0...develop
[Unreleased]: https://github.com/brainelectronics/micropython-nextion/compare/0.12.0...develop

[0.12.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.12.0
[0.11.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.11.0
[0.10.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.10.0
[0.9.0]: https://github.com/brainelectronics/micropython-nextion/tree/0.9.0
Expand Down
20 changes: 19 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
| [Picture](picture) | NexPicture | :x: |
| [Progress](progress) | NexProgress | :heavy_check_mark: |
| [Radio](radio) | NexRadio | :heavy_check_mark: |
| [Rtc](rtc) | NexRtc | :x: |
| [Rtc](rtc) | NexRtc | :heavy_check_mark: |
| [Scrolltext](scrolltext) | NexScrolltext | :x: |
| [Slider](slider) | NexSlider | :heavy_check_mark: |
| [Text](text) | NexText | :heavy_check_mark: |
Expand All @@ -36,3 +36,21 @@ elements by simple UART command calls.

The [hardware example](hardware/main.py) shows the usage of the hardware
functions `sleep`, `brightness` and `reset`.

## Upload example

The [upload example](upload/main.py) shows how to update a Nextion display
with a new TFT file.

Copy the [example TFT file](everything.tft) to the MicroPython board with
e.g. `rshell`

```bash
rshell --port /dev/tty.SLAB_USBtoUART --editor nano
```

Copy the file to the device, this might take several minutes!

```bash
cp everything.tft /pyboard
```
100 changes: 100 additions & 0 deletions examples/rtc/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

"""
Main script
Do your stuff here, this file is similar to the loop() function on Arduino
Example on how to interact with a RTC
"""

# system packages
import time

# custom packages
from nextion import NexHardware, NexRtc

# define communication pins for Nextion display
tx_pin = 21
rx_pin = 22

# create Nextion hardware interface
nh = NexHardware(rx_pin=rx_pin, tx_pin=tx_pin)

# init nextion communication interface
nh.nexInit()

# create a RTC instance
rtc = NexRtc(nh)

# ============================================================================
# ============================ Sync time with NTP ============================
try:
import network
import ntptime

station = network.WLAN(network.STA_IF)
if station.isconnected():
ntptime.settime()
else:
print('Device not connected to the internet, using available time')
except Exception as e:
print('Unexpected exception {} occured, using available time'.format(e))

# cut off weekday and yearday, keep [year, month, mday, hour, minute, second]
localtime = list(time.localtime())[0:6]

# ============================================================================
# ============================ Set RTC functions =============================
# set RTC time to list of integers '[2022, 7, 30, 18, 21, 45]'
print('Set RTC time to: {}'.format(localtime))
rtc.write_rtc_time(localtime)
print()

time.sleep(1)

# set RTC time to time string '2022,07,30,18,21,45'
localtime_str = ','.join('{:02d}'.format(x) for x in localtime)
print('Set RTC time to: "{}"'.format(localtime_str))
rtc.write_rtc_time(localtime_str)
print()

time.sleep(1)

# set only year of RTC
print('Set only year of RTC to: "{}"'.format(localtime[0]))
rtc.write_rtc_time('year', localtime[0])
print()

time.sleep(1)

# ============================================================================
# ============================ Get RTC functions =============================
# get RTC time as string
response = rtc.read_rtc_time('str')
print('Timestamp from RTC as string: "{}"'.format(response))
print()

time.sleep(1)

# get RTC time as list of integers
response = rtc.read_rtc_time('int')
print('Timestamp from RTC list of integers: "{}"'.format(response))
print()

time.sleep(1)

# get available time types from RTC one by one
print('Get individual time types from RTC...')
for time_type in rtc.time_types:
response = rtc.read_rtc_time(time_type)
print('{} by RTC: "{}"'.format(time_type, response))
print()

# ============================================================================
# ============================= End of example ===============================
print('Returning to REPL in 5 seconds')

# wait for 5 more seconds to safely finish the may still running threads
time.sleep(5)
1 change: 1 addition & 0 deletions nextion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .nextion_page import NexPage
from .nextion_progressbar import NexProgressBar
from .nextion_radio import NexRadio
from .nextion_rtc import NexRtc
from .nextion_slider import NexSlider
from .nextion_text import NexText
from .nextion_upload import NexUpload
Expand Down
212 changes: 212 additions & 0 deletions nextion/nextion_rtc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

"""
NexRtc
Functions to interact with Nextion RTC
"""

# system packages
from time import sleep

# custom packages
from .common import Common
from .typing import List, Optional, Union


class NexRtcError(Exception):
"""Base class for exceptions in this module."""
pass


class NexRtc(Common):
"""docstring for NexRtc"""
def __init__(self, nh) -> None:
"""
Init RTC
:param nh: The Nextion hardware interface object
:type nh: NexHardware
"""
super().__init__(nh, pid=-1, cid=-1, name="rtc")

self._time_types = ["year", "mon", "day", "hour", "min", "sec", "week"]

@property
def time_types(self) -> List[str]:
"""
Get available time types
:returns: Requestable time types from RTC
:rtype: List[str]
"""
return self._time_types

def write_rtc_time(self, *args, **kwargs) -> bool:
"""
Write time to RTC
:param time: The time to set the RTC
:type time: Union[str, List[int]]
:param time_type: The type of time to change
:type time_type: str
:returns: True on success, False otherwise
:rtype: bool
"""
if (len(args) + len(kwargs) == 1):
# only a time is given
if len(args):
time = args[0]
else:
time = kwargs["time"]
if isinstance(time, str) and len(time) >= 19:
# "2016,11,25,12,34,50"
year = time[0:4]
month = time[5:7]
day = time[8:10]
hour = time[11:13]
minute = time[14:16]
second = time[17:19]
elif (isinstance(time, list) and
all(isinstance(x, int) for x in time)):
# [2016, 11, 25, 12, 34, 50]
year = time[0]
month = time[1]
day = time[2]
hour = time[3]
minute = time[4]
second = time[5]
else:
raise NexRtcError("Time can either be given as '{}' or '{}'".
format("2016,11,25,12,34,50",
[2016, 11, 25, 12, 34, 50]))

self._nh._logger.debug("Timestamp (ISO8601): {}-{}-{}T{}:{}:{}".
format(year, month, day, hour, minute,
second))

cmd = "rtc0={}".format(year)
self._nh.sendCommand(cmd)
self._nh.recvRetCommandFinished()

cmd = "rtc1={}".format(month)
self._nh.sendCommand(cmd)
self._nh.recvRetCommandFinished()

cmd = "rtc2={}".format(day)
self._nh.sendCommand(cmd)
self._nh.recvRetCommandFinished()

cmd = "rtc3={}".format(hour)
self._nh.sendCommand(cmd)
self._nh.recvRetCommandFinished()

cmd = "rtc4={}".format(minute)
self._nh.sendCommand(cmd)
self._nh.recvRetCommandFinished()

cmd = "rtc5={}".format(second)
self._nh.sendCommand(cmd)
return self._nh.recvRetCommandFinished()
elif (len(args) + len(kwargs) == 2):
# time_type is given as well
if len(kwargs) == 2:
time_type = kwargs['time_type']
time = kwargs['time']
else:
if len(args) == 2:
time_type = args[0]
time = args[1]
else:
raise NexRtcError("Either use keyword or positional args")

self._nh._logger.debug("Set '{}' to '{}'".format(time_type, time))
rtc_index = self.time_types.index(time_type.lower())

cmd = "rtc{}={}".format(rtc_index, time)
self._nh.sendCommand(cmd)
return self._nh.recvRetCommandFinished()
else:
raise NexRtcError("Only two args are allowed")

def read_rtc_time(self,
return_type: str,
length: Optional[int] = 22) -> Union[str, List[int]]:
"""
Read RTC time
:param return_type: The return type, choose "int", "str" or from
["year", "mon", "day", "hour", "min", "sec",
"week"]
:type return_type: str
:param length: The length
:type length: Optional[int]
:returns: RTC time
:rtype: Union[str, List[int]]
"""
return_type = return_type.lower()

if return_type in ["str", "int"]:
cmd = "get rtc0"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
year = self._nh.recvRetNumber()

cmd = "get rtc1"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
month = self._nh.recvRetNumber()

cmd = "get rtc2"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
day = self._nh.recvRetNumber()

cmd = "get rtc3"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
hour = self._nh.recvRetNumber()

cmd = "get rtc4"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
minute = self._nh.recvRetNumber()

cmd = "get rtc5"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
second = self._nh.recvRetNumber()

cmd = "get rtc6"
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
week = self._nh.recvRetNumber()

time_buf = [year, month, day, hour, minute, second, week]

if return_type == "str":
time_string = ("{}/{}/{} {}:{}:{} {}".
format(year, month, day, hour, minute, second,
week))
if length >= 22:
return time_string
else:
return time_string[0:length]
elif return_type == "int":
if length >= 7:
return time_buf
else:
return time_buf[0:length]
elif return_type in self.time_types:
rtc_index = self.time_types.index(return_type)
cmd = "get rtc{}".format(rtc_index)
self._nh.sendCommand(cmd)
sleep(0.1) # necessary, data might not be available otherwise
return self._nh.recvRetNumber()
else:
raise NexRtcError("RTC time can only be returned as '{}' or '{}'"
"or chosen from {}".
format("str", "int", self.time_types))

0 comments on commit 0c28b07

Please sign in to comment.