前回、ログファイルのタイムスタンプを正確な時刻にするため、GNSS受信機データから時間情報を抽出し、OS(Linux)の正確な時間に更新するpythonプログラムを作成し、動作確認まで到達。
GNSS受信プログラムとの統合と不具合と修正
OS時間更新プログラムとGNSS受信プログラムを統合し、自動起動のためのsystemd用設定ファイルに登録するが、自動起動がされない不具合が発生。
pythonプログラム自体を直接実行すると正常に動作する。
ログを調べてみる。
$ sudo systemctl status autognssctrl.service ● autognssctrl.service - Auto GNSS Control program Loaded: loaded (/etc/systemd/system/autognssctrl.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Fri 2021-04-02 02:52:06 UTC; 2 years 7 months ago Process: 463 ExecStart=/usr/bin/python3 /home/yuji/python_work/work_gnsslogger_006.py (code=exited, status=1/FAILURE) Main PID: 463 (code=exited, status=1/FAILURE) Apr 02 02:52:01 NanoPi-NEO systemd[1]: Started Auto GNSS Control program. Apr 02 02:52:06 NanoPi-NEO python3[463]: Traceback (most recent call last): Apr 02 02:52:06 NanoPi-NEO python3[463]: File "/home/yuji/python_work/work_gnsslogger_006.py", line 6, in Apr 02 02:52:06 NanoPi-NEO python3[463]: import serial Apr 02 02:52:06 NanoPi-NEO python3[463]: ImportError: No module named 'serial' Apr 02 02:52:06 NanoPi-NEO systemd[1]: autognssctrl.service: Main process exited, code=exited, status=1/FAILURE Apr 02 02:52:06 NanoPi-NEO systemd[1]: autognssctrl.service: Unit entered failed state. Apr 02 02:52:06 NanoPi-NEO systemd[1]: autognssctrl.service: Failed with result 'exit-code'.
import serial でエラーが出ている
ネットを調べたり試行錯誤の末、systemdが動作する起動時のユーザーや権限の環境とプログラムが正常動作する現在の環境が違っていることがわかり、合わせるように修正。
修正前:
$ cat /etc/systemd/system/autognssctrl.service [Unit] Description=Auto GNSS Control program [Service] ExecStart=/usr/bin/python3 /home/yuji/python_work/work_gnsslogger_006.py [Install] WantedBy=multi-user.target
修正後:
$ cat /etc/systemd/system/autognssctrl.service [Unit] Description=Auto GNSS Control program [Service] ExecStart=/usr/bin/sudo /usr/bin/python3 /home/yuji/python_work/work_gnsslogger_006.py User=yuji [Install] WantedBy=multi-user.target
この修正により、起動直後からGNSS受信プログラムが自動実行されることを確認。
タイムゾーンの設定
GNSS受信プログラムが自動実行されたので、ボタンを押してログ取得を行い、LANケーブルを挿して母艦から共有フォルダにあるログファイルを確認したところ、タイムスタンプがおかしい。
以前のようにOSイメージ作成時の数年前のタイムスタンプではないが半日近くずれている。
タイムゾーンが日本に設定されていないことが判明。
$ date Sun Nov 12 11:04:43 UTC 2023 $ sudo timedatectl set-timezone Asia/Tokyo $ date Sun Nov 12 20:20:12 JST 2023
これでログファイルのタイムスタンプも正しく反映されることを確認
統合したプログラム
ここまで作成したpythonプログラムは以下の通り
#!/usr/bin/python3 #import sys import subprocess import re from datetime import datetime, timedelta, timezone import serial import serial.serialutil as srlutil import RPi.GPIO as GPIO import time #PA0 PIN_NUM_LED = 11 #PA3 PIN_NUM_SWITCH = 15 GPIO.setmode(GPIO.BOARD) GPIO.setup(PIN_NUM_LED, GPIO.OUT) GPIO.setup(PIN_NUM_SWITCH, GPIO.IN, pull_up_down=GPIO.PUD_UP) pwm = GPIO.PWM (PIN_NUM_LED,0.2) pwm.start(20) timezone = 9 dtnow = datetime.now() print(dtnow) ser = serial.Serial("/dev/ttyACM0", 115200, timeout=2) while True: rsvline = ser.readline() if rsvline[0] != ord("$"): ser.reset_input_buffer() continue try: line = rsvline.decode('ascii') except Exception as e: print(e) ser.reset_input_buffer() continue line = line.strip() items = line.split(",") if re.search("\$..RMC",items[0]): print(line) (dummy1,day,month,year,dummy2)= re.split("(..)(..)(..)",items[9]) (dummy1,hour,minute,sec,msec10,dummy2) = re.split("(..)(..)(..)\.(.*)",items[1]) print("20%s/%s/%s %s:%s:%s.%s"%(year,month,day,hour,minute,sec,msec10)) dt = datetime(2000 + int(year),int(month),int(day), int(hour),int(minute),int(sec),int(msec10)*10000) + timedelta(hours=timezone) if dt > dtnow: ser.close() gnsstime = dt.strftime("%Y-%m-%d %H:%M:%S") subprocess.call(["/usr/bin/timedatectl", "set-time", gnsstime]) dtnow = datetime.now() print(dtnow) #sys.exit(0) break ser.reset_input_buffer() ser.close() pwm.ChangeFrequency(1) cmd="str2str -in serial://ttyACM0:115200#ubx -out /home/share/`date +%Y%m%d%H%M%S`.ubx" state=0 try: while True: if GPIO.input(PIN_NUM_SWITCH)==0: time.sleep(1) #0.1s wait if state==0: subrun=subprocess.Popen("exec " + cmd, shell=True) pwm.ChangeDutyCycle(20) state=1 elif state==1: subrun.kill() pwm.ChangeDutyCycle(0) state=0 except KeyboardInterrupt: pass pwm.stop() GPIO.cleanup()