yseosys
@yseosys (瀬尾)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Raspberry Pi systemdによる自動起動

解決したいこと

Raspberry Pi Python 3.7で電源onで自動起動させ
wifi接続してサーバーにデータを送りたいのですが、
うまくうごきません。
自動起動以外(サービス起動及びパイソンプログラム起動)の時は問題なく動作します。
解決方法を教えてください。

発生している問題・エラー

a.service - do websens
   Loaded: loaded (/etc/systemd/system/a.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Mon 2020-10-12 10:36:51 JST; 30min ago
  Process: 844 ExecStart=/usr/bin/python3.7 /opt/mybin/web2.py (code=exited, status=1/FAILURE)
 Main PID: 844 (code=exited, status=1/FAILURE)

10月 12 10:36:51 raspberrypi python3.7[844]:     return session.request(method=method, url=url, **kwargs)
10月 12 10:36:51 raspberrypi python3.7[844]:   File "/usr/lib/python3/dist-packages/requests/sessions.py", line 533, in request
10月 12 10:36:51 raspberrypi python3.7[844]:     resp = self.send(prep, **send_kwargs)
10月 12 10:36:51 raspberrypi python3.7[844]:   File "/usr/lib/python3/dist-packages/requests/sessions.py", line 646, in send
10月 12 10:36:51 raspberrypi python3.7[844]:     r = adapter.send(request, **kwargs)
10月 12 10:36:51 raspberrypi python3.7[844]:   File "/usr/lib/python3/dist-packages/requests/adapters.py", line 516, in send
10月 12 10:36:51 raspberrypi python3.7[844]:     raise ConnectionError(e, request=request)
10月 12 10:36:51 raspberrypi python3.7[844]: requests.exceptions.ConnectionError: HTTPConnectionPool(host='192.168.180.133', port=80): Max retries exceeded with url: /wifi2/sensor.php (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0xb5da3290>: Failed to establish a new connection: [Errno 101] Network is unreachable'))
10月 12 10:36:51 raspberrypi systemd[1]: a.service: Main process exited, code=exited, status=1/FAILURE
10月 12 10:36:51 raspberrypi systemd[1]: a.service: Failed with result 'exit-code'.

該当するソースコード1(web2.py)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import requests
import json
from datetime import datetime


def uploadSensorValues(red,green,blue,cData,ax,ay,az,tt,gx,gy,gz):    

   url = 'http://192.168.180.133/wifi2/sensor.php'
   sensorsdata = 0,datetime.now().strftime("%Y/%m/%d"),datetime.now().strftime("%H:%M:%S"),red,green,blue,cData,ax,ay,az,tt,gx,gy,gz,0
   print("送り")
   print (json.dumps(sensorsdata))
   r = requests.post(url, data=json.dumps(sensorsdata)stoptimeout=20)



def main():

    uploadSensorValues(28, 39, 47, 56, 128,200,256,512,300,233,300)


if __name__ == '__main__':

該当するソースコード2(a.service)

[Unit]
Description=do websens
After=bluetooth.target bluetooth.service 

[Service]
ExecStart=/usr/bin/python3.7 /opt/mybin/web2.py
Restart=alway
Type=simple

[Install]
WantedBy=bluetooth.target

サービス起動で動かしてうまくいったとき

pi@raspberrypi:~ $ sudo systemctl stop a
pi@raspberrypi:~ $ sudo systemctl start a
pi@raspberrypi:~ $ sudo systemctl status a
● a.service - do websens
   Loaded: loaded (/etc/systemd/system/a.service; enabled; vendor preset: enable
   Active: inactive (dead) since Mon 2020-10-12 11:26:03 JST; 33s ago
  Process: 3048 ExecStart=/usr/bin/python3.7 /opt/mybin/web2.py (code=exited, st
 Main PID: 3048 (code=exited, status=0/SUCCESS)

10月 12 11:26:02 raspberrypi systemd[1]: Started do websens.
10月 12 11:26:03 raspberrypi python3.7[3048]: 送り
10月 12 11:26:03 raspberrypi python3.7[3048]: [0, "2020/10/12", "11:26:02", 28, 
10月 12 11:26:03 raspberrypi systemd[1]: a.service: Succeeded.

自分で試したこと

[Install]WantedBy=bluetooth.targetは最初はmulti-user.targetにしていたのですが、systemd-analyze plot > plot.svgでサービスの立ち上げをチェックしa.serviceを一番最後にするために変更しました。

0

1Answer

[Errno 101] Network is unreachableとなっているので、network interfaceが起動しきる前にserviceが起動しているために、サーバーに接続しきれていないと思われます。

対応としては、以下の2つの方法が考えられます。

  1. 自作プログラム上でネットワークが起動するまでリトライをする
  2. serviceがネットワーク起動後に起動するように依存関係を設定する

1.の場合は、request.postにリトライ用のエラー処理を追加すれば良いかと思います。
例えば下記のコードのようにすれば、15秒待ってリトライを10回します。

import time
import equests.exceptions

retrycount = 0
while True:
    try:
        r = requests.post(url, data=json.dumps(sensorsdata), timeout=20)
    except requests.exceptions.ConnectionError:
        if retrycount > 10:
            retrycount += 1
            time.sleep(15)
            continue
        raise

2.の場合、systemd-networkd-wait-onlineを使うのがいいかと思います
この記事が参考になるかとおもいます。
https://kernhack.hatenablog.com/entry/2014/09/20/110938

2Like

Comments

  1. @yseosys

    Questioner

    1.のエラーが出たらリトライする処理を追加することにより無事データを送ることができるようになりました。ありがとうございます。

Your answer might help someone💌