rasberry pi 3 で 計数カウンタを作成する6 -ソケット通信 クライアント再接続

さて、前回カウンターの値を、ソケット通信でサーバに接続して、

送るところまでやりましたが、

 

サーバを一度落としてしまうと、

サーバが再起動しても、クライアントの再接続がなかなかできず、苦労しました。

 

最終的に実現した方法は。

① カウントのプログラムは独立させて、カウントをテキストに記録し続ける。

② 通信プログラムを用意し、カウントのテキストを読み込んで、サーバに送信する。

③ サーバへの送信に失敗したら、シェルスクリプトを使用して、通信プログラムを再起動し、自分は終了する。

④ 通信プログラムは接続できるまで待機し続けるので、サーバが再起動されると、再接続される。

 

最初は計数のカウントと通信を同時にpython でやろうとしたのですが、

計数カウントを取り続けながら、サーバへ再接続するのが難しくて、

分離して単純化しました。

 

通信プログラムで、サーバへの送信が失敗した時に、単純に再接続しようとしましたが、うまくいきませんでした。再接続不能になるか、何度も接続と切断を繰り返してしまうような挙動になってしまいました。

うまくいかないので、通信プログラム自体を再起動することにし、シェルスクリプトで実装しました。

 

以下、新しいカウンターのプログラム

 

import RPi.GPIO as GPIO
import struct
import time
from time import sleep
import socket
import sys

def write_count(count):
    f = open('/home/XXXXX/count.txt' ,'w')
    f.write(str(count))
    f.close()

def callBackRising(channel):
    if GPIO.input(24):
    # GPIO.output(25,GPIO.HIGH)
    global count
    count += 1
    try:
        print(str(count))
        write_count(count)
    except:
        pass
    else :
        pass
        # GPIO.output(25,GPIO.LOW)
def read_do():
    f = open('/home/XXXXX/do.txt','r')
    doStr = f.read()
    if (doStr == 'True'):
        return True
    elif (doStr == 'False'):
        return False
    else:
        return True

def main():

    GPIO.setmode(GPIO.BCM)
    GPIO.setup(25, GPIO.OUT)
    global count
    count = 0
    f = open("/home/XXXXX/count.txt","r")
    countstr = f.read()
    try:
        count = int(countstr)
    except:
        count = 0

    pin = 24
    flg = False

    #start_time = time.time() - start_time

    GPIO.setup(pin, GPIO.IN)
    #GPIO.add_event_detect(pin, GPIO.RISING, callback=callBackRising,bouncetime=100)  
    #GPIO.add_event_detect(pin, GPIO.FALLING, callback=callBackFalling, bouncetime=150)
    GPIO.add_event_detect(pin, GPIO.BOTH, callback=callBackRising, bouncetime=200)

    DoFlg = True
    count_try = 0
    try:
        while DoFlg:
            DoFlg = read_do
            sleep(1)

        finallizeFlg = False;
        c_socket.close()
        GPIO.cleanup()

    except KeyboardInterrupt:
        print("end cleanup")
        GPIO.cleanup()

if __name__ == '__main__':
main()

 

***********ここまでがカウンター**************************************************

 

次は通信プログラムです。


import struct
import time
from time import sleep
import socket
import sys
import signal
import os


HOSTNAME = "192.168.30.131"
PORT = 8600
INTERVAL = 3
RETRYTIMES = 1

global c_socket
def write_count(count):
f = open('/home/shared/tp-1/count.txt' ,'w')
f.write(str(count))
f.close()

def read_do():
    f = open('/home/shared/tp-1/do.txt','r')
    doStr = f.read()
    if (doStr == 'True'):
        return True
    elif (doStr == 'False'):
        return False
    else:
        return True
def read_count():
    f = open('/home/shared/tp-1/count.txt','r')
    countStr = f.read()
    try:
        return int(countStr)
    except:
        pass

def SendCount(arg1, arg2):
    try:
        count = read_count()
        c_socket.send(str(count))
    except:
        savelog('exception happend')
        os.system('/home/hsmt_system/XXXXXX/restart.sh &')
        savelog('after sh')
        sys.exit(0)

def savelog(msg):
    f = open('/home/hsmt_system/h_counter/log.txt' ,'a')
    f.write(str(msg) + '\n')
    f.close()

def socket_connect(host, port, interval, retries):
    global c_socket
    c_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    for x in range(retries):
        try:
            c_socket.connect*1
            return c_socket
        except socket.error:
            print "wait"+str(interval)+"s"
            time.sleep(interval)

    c_socket.close()
    return None

def main():
    passFlg = False
    c_socket = socket_connect(HOSTNAME,PORT,INTERVAL,RETRYTIMES)

    while c_socket is None:
        c_socket = socket_connect(HOSTNAME,PORT,INTERVAL,RETRYTIMES)

    if c_socket is None:
        print "system exit:connection error"
        sys.exit(0)

if __name__ == '__main__':
main()

signal.signal(signal.SIGALRM, SendCount)
signal.setitimer(signal.ITIMER_REAL, 0.2, 0.2)

connectFlg = False

errorFlg = False
while True:
    time.sleep(1)

try:
    c_socket.close()
    GPIO.cleanup()

except KeyboardInterrupt:
    print("end cleanup")
    c_socket.close()

 

*************ここまでが通信プログラム**********************************

 

最後に、再起動用のシェルスクリプトです。

 

#!/bin/sh

python /home/xxxx.py

*1:host, port

Yamaha ルーター RTX810を使用した、ネットワーク構築 -1 ルーティング,ping

拠点1 2 3 がVPNでつながっています。

RTX810 が各拠点にあって、フレッツ光VPNのサービスを使用しています。

f:id:hsmtblue:20171027013327p:plain

拠点2に新しいネットワークを追加し、ルーティングします。

RTX810を追加して、その下の島を新たなネットワークとします。

 

f:id:hsmtblue:20171027014505p:plain

拠点2の事務所のネットワークを 2-1 , 新たなネットワークを 2-2

と呼ぶことにします。

2-1 のセグメントを 192.168.1.0/24

2-2のセグメントを 192.168.2.0/24 とします。

まずは新しく追加したRTX810 の設定を見てみましょう。

 

ip route default gateway 192.168.1.1

ip lan1 address 192.168.2.1/24
ip lan2 address 192.168.1.225/24

と設定します。 lan1 を新しいネットワークに、

lan2をもともとあるネットワークに物理的に接続します。

 

基本的にはこれでいいはずですが、なぜか192.168.2.0/24 のどこかにping を送っても

とどかない・・・。

実は192.168.1.0/24 のネットワークから 192.168.2.0/24 へ通信しようとすると、

192.168.1.1 のルータに192.168.2.0/24 はどこですか?と聞きに行くのですが、

今の状態だとルーティング情報がないので、たどり着くことができません。

ping は行って戻ってくるものなので、これでは行けても戻ってこれないわけです。

 

なので、192.168.1.1のルータに新たな経路情報を追加します。

ip route 192.168.2.0/24 gateway 192.168.1.225

これで2 のネットワークに通信しようとすると、192.168.2.225のルータに

飛ばされ、そのルータは2のネットワークに接続されているので通信可能になります。

 

これでping が通るようになるはずです。

 

 

rasberry pi 3 で 計数カウンタを作成する5 -python

以下に、カウンターで使用しているパイソンのプログラムを掲載します。

サーバに接続して、カウントするごとに数値をサーバに送るようにしています。サーバはVB.net  で作成しました。

ここにはクライアントのパイソンのみ掲載します。

import RPi.GPIO as GPIO
import struct
import time
from time import sleep
import socket
import sys

#サーバのIPとポートの設定
HOSTNAME = "192.168.XXX.XXX"
PORT = XXXX
INTERVAL = 3
RETRYTIMES = 10

#以下でソケットを作成して、サーバに接続しに行きます。

#接続に失敗した場合は、接続できるまで再試行を繰り返します。


global c_socket

def socket_connect(host, port, interval, retries):
global c_socket
c_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

for x in range(retries):
    try:
        c_socket.connect*1
        return c_socket
    except socket.error:
        print "wait"+str(interval)+"s"
        time.sleep(interval)

  c_socket.close()
  return None

def main():
    c_socket = socket_connect(HOSTNAME,PORT,INTERVAL,RETRYTIMES)
    while c_socket is None:
        c_socket = socket_connect(HOSTNAME,PORT,INTERVAL,RETRYTIMES)

if c_socket is None:
    print "system exit:connection error"
    sys.exit(0)

if __name__ == '__main__':
    main()

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT)
global _COUNT_PATH

#接続が切れた場合に、カウントし続け、以下のパスのファイルにカウントを記録する。
_COUNT_PATH = '/home/shared/count.bin'
global count
count = 0

#起動時にファイルからカウントを復旧する
f = open("/home/shared/tp-1/count.txt","r")
countstr = f.read() 
count = int(countstr)
pin = 24
flg = False

#ファイルにカウントを書き込む
def write_count(count):
   f = open('/home/shared/tp-1/count.txt' ,'w')
    f.write(str(count))
    f.close() 


#センサーの反応の立ち上がりの処理
def callBackRising(channel):
    if GPIO.input(24):
        GPIO.output(25,GPIO.HIGH)
        global count
        count += 1
    try:
         c_socket.send(str(count))
    except:
        pass
        print(str(count))
        write_count(count)
    else :
        GPIO.output(25,GPIO.LOW)

GPIO.setup(pin, GPIO.IN)
#GPIO.add_event_detect(pin, GPIO.RISING, callback=callBackRising, bouncetime=100)
#GPIO.add_event_detect(pin, GPIO.FALLING, callback=callBackFalling, bouncetime=150)
GPIO.add_event_detect(pin, GPIO.BOTH, callback=callBackRising, bouncetime=200)

 

#以下、サーバから命令が来た時の処理
DoFlg = True
try:
    while DoFlg:
        sleep(1)
        response = c_socket.recv(1024)
        print(response)
        if response == 'END':
            DoFlg = False
        elif response == 'RESET':
            count =0
        elif response == 'SEND':
            c_socket.send(str(count))
    finallizeFlg = False;
    c_socket.close()
    GPIO.cleanup()

except KeyboardInterrupt:
    print("end cleanup")
    c_socket.close()
    GPIO.cleanup()

*1:host, port

Windows10 NTPサーバが動作しない

社内の閉鎖ネットワークにWindows10で動作するNTPサーバがあるのですが、

気づいたら動作していませんでした。

Windows 10 をNTPサーバにする手順 | 無停電電源装置(UPS) | イートン

 

この手順でやり直しましたが、net start w32time

をプロンプトから実行すると

「エラー1058指定されたサービスは無効であるかまたは有効なデバイスが関連付けられていないため開始できません」

 

と出る。・・・・。Windows10のNTPサーバ機能使えなくなったのかな?

と思いましたが、そんなことは検索しても出てこない。

Service のところを探してもw32time はない。

色々試すがダメ。桜時計という、NTPのソフトを使ってみてもダメ。

 

結論

設定の、日付と時刻のところで、時刻を自動的に設定するがオフになっていました。

 オン、にしたらなおりました

良かった。

Yamaha ルーター RTX810を使用した、ネットワーク構築 -0 

拠点1、2、3がVPNで接続されています。

各拠点において、無線LANアクセスポイントを設置するのですが、

今ある拠点間LANのネットワークとは切り離しつつ、

インターネットアクセスが可能な環境を作り上げることになりました。

 

インターネットをブラウジング可能な島からは、ファイルサーバと、他クライアントPCのある島への接続は不可。

ファイルサーバのある島からは、他拠点への接続は可。

webのブラウジングは不可。

しかしwindows update 等の、更新はしっかりと行う必要があるので、

ブラウザをブロックするソフトを使用することにより、

ウェブ閲覧を行う島と、そうでない島を分離して、セキュリティの向上をはかります。

 

その学習とメモを今後更新していく予定です。

 

YAMAHA RTX810 vpnルーターで シリアル通信ができない 

www.amazon.co.jp

 USB変換ケーブルでシリアル通信しようとしたがうまくいかない。

 

www.amazon.co.jp

これも必要。

www.amazon.co.jp

これも必要。

 

しかし、接続できない・・・。

USBではなく、普通のシリアルケーブルでRS232cポートのあるPCでも

なぜか通信できない。

クロスケーブルでいいはず。

 

コンソールはTeraTerm

!!!

カーソルがあって反応しているような気がしたので、

エンター押したらつながっていました。

 

エンター押してみてください!!!

 

 

Orphis X7250 で、スキャナーの保存先に指定したSambaがアクセス不能になりました。

RISO のプリンター複合機 X7250 で、

スキャナーの保存先にしているLinuxServerのフォルダにアクセスできないようで、

「保存できません」とエラーが。

 

そういえばSambaのバージョンが上がってからWindowsServer2003からアクセス不能になったりしたのを思い出しました。

 

X7250にログインして、設定を見てみましたが、

NTLMv2を使用するような項目は見当たらない。

 

とりえず、

サーバー側でNTLMv1へ対応する設定を追加

/etc/samba/smb.confの globalセクションに

ntlm auth = yes

を追加してみると、

ちゃんと保存できました。

 

はたして、X7250側での対応は可能なのでしょうか・・・。