前回はプログラムを起動すると、Webから情報取得→LED点滅パターンに変換→LED点滅制御、と一連の動作をプログラムにまとめました。今回は、設定した時刻にWebから情報を取得して、LED点滅パターンを更新してみます。前回のプログラムでは、起動した時にWebから天気予報情報と鉄道運行状況の情報を取得してLED点滅制御しましたが、LEDの点滅制御が始まるとそのままでした。今回は、あらかじめ指定した時刻になったらWebから情報を再取得して情報更新、LED点滅パターン更新をする仕組みを実装してみます。鉄道運行状況については最新の情報を知りたいケースもあると思いますので、スイッチを押したら情報更新するプログラムも追加してみます。プログラム中に更新時刻をハードコードしてしまうと、あとで修正するのが面倒になりますので、時刻設定の仕様あたりから検討してみたいと思います。今回は以下の内容で説明します。特定の時刻になったらWebから情報を再取得する方法として、プログラム中のLEDを点滅制御するループ内で、指定時刻になったか確認し、指定時刻になったらWebから情報を再取得すればよさそうです。具体的な指定時刻をループ内に記述してしまうと、あとからその時刻を変更するとき修正が面倒です。そこで情報更新の時刻指定は、プログラムの最初に、PHPであれば配列、Pythonであればリストに指定しておく、という方法にしたいと思います。いうフォーマットでプログラムの最初で指定しておくと、取得時刻の変更をする場合は便利ですよね。取得時刻を増やしたい場合も(減らしたい場合も)、以下のように単純に配列の要素を増やせばいいようにしておけば、今後のプログラムのメンテも楽になると思います。"20:30"];ということで、時刻指定はプログラムの最初で配列(PHP)またはリスト(Python)で指定しておく方式にしたいと思います。指定時刻になったらWebから情報を再取得するために、まずプログラム全体を整理しておきます。具体的には、情報を取得してLED点滅パターンに変換するコードを関数にしておき、更新時はその関数を呼び出すことにします。点滅制御のループ内で情報の取得時刻になったかどうかのチェックをしますので、取得時刻になったらその関数を呼び出す、という実装にしようと思います。イメージとしては以下のような感じです。プログラムの最初で、取得時刻を配列に入れておきます。メイン処理では、LEDの点滅制御を繰り返しますので、LEDの点滅制御が1パターン分終わるごとに「次の取得時刻になったか」判定して、取得時刻になれば関数を呼び出して情報更新、LED点滅パターン更新すればOKそうです。なんだか簡単そうですよね。言葉で書くのは簡単ですが、プログラムで書くのは意外に大変です。そこで、この判定については、先にPHPでアルゴリズムを検討、動作確認することにします。「次の取得時刻になったか」の判定はどのように行えばいいでしょうか。この判定条件をもうちょっと正確に書くと「現在の時刻と次の取得時刻を比較して、現在の時刻が次の取得時刻を過ぎたか」という判定になります。情報更新;}という判定になります。ところで、プログラム中、時刻はどのように扱うのでしょうか。プログラムでは、時刻を扱う一つの方法としてUNIX時間というものがあります。UNIX時間(UNIXタイムスタンプなどとも呼ばれています)とは、1970年1月1日の0時0分0秒を起点としてカウントした現時点の経過秒数になります。以下のプログラムで現在のUNIX時間を表示することができます。time();?>例えばこの記事を書いている日時は、2019年5月12日の16時頃ですが、上のプログラムを実行すると、UNIX時間は1557642910と表示されました。15億5764万2910秒ということになります。なんか数字が大きすぎて感覚がよくわからないですよね。このUNIX時間を使えば、情報を更新する部分のプログラムは以下のように記述できそうです。情報更新;}では「次の取得時刻のUNIX時間」を求めるにはどうしたらよいか、考えていきます。取得時刻は以下のように準備しました。形式で見つけて、それをUNIX時間に変換すればよさそうです。いう関数は用意されているはず、ということで検討を進めます。それでは最初に、”hh:mm”形式で次に取得する時刻を探してみます。現在の時刻が13:30の時を考えてみます。この正解にたどり着く方法を検討してみましょう。ひとつの方法として、”13:30′′という文字列を、$timeToGet配列の要素の最初から、つまりインデックス0の要素から比較していけば求められそうです。“06:30′′と比較します。(文字列の比較はアルファベット順の比較になります。次の取得時刻ではありません。“13:30′′の方が大きいので次の取得時刻ではありません。”17:30′′と比較すると、今度は”13:30′′の方が小さいため、”17:30′′が次の取得時刻、と判定できます。大きい文字列はありません。「翌日の」”06:30′′が取得時刻になります。翌日の日付を求める処理が必要になります。それぞれ確認していきましょう。形式で取得したい場合、date()関数を使います。UNIX時間);です。UNIX時間);とします。time());とすればOKです。Piで動作確認してみてください。date()関数ではUNIX時間から年月日の文字列も取得することが可能です。4桁の西暦で年月日を取得するには以下のようにします。time());この関数を実行すると、例えば2016/01/30などの文字列が取得できます。分かったとしても、それをUNIX時間に変換しておく必要があります。このような変換に対してもきちんと関数が用意されています。strtotime()関数で行います。パラメータは現在の時刻文字列です。以下のように指定すると、指定した日時文字列に対するUNIX時間が取得できます。12:57");ところで、場合によっては翌日を求めることになりますが、これもstrtotime()関数でできてしまいます。時刻文字列の翌日を求めるには、以下のようにします。UNIX時間);例えば、以下のようにすると、現在の時刻の翌日の日時が求められます。うるう年とかの計算もしてくれるので助かりますね。試作プログラムそれでは、実際に確認用にプログラムを作成してみます。$timeToGet配列に、取得する時刻を入れておき、現在の時刻を取得して、次の取得時刻を算出する、という処理を行うプログラムになります。プログラム中説明するところはないと思います。コメントを見ながら処理を追ってみてください。現在の時刻を取得する処理は14行目、15行目ですが、デバッグ用に18行目で確認したい時刻を設定するようにしています。本当の現在の時刻でテストしたい場合は、18行目をコメントアウトしてください。なるか、などの確認をしたい場合は、18行目に確認したい時刻を設定します。制御ループは100回にしています。ループ1回で約3秒ですので、100回で300秒、つまり5分程度です。取得時刻に対して制御ループの動作時間が短いので、取得時刻に合わせて情報が更新されるのか確認したい場合は以下のようにデバッグするといいと思います。現在の時刻が14:30である場合、プログラムを動作すると14:35ぐらいまで動きます。“14:32′′、”14:34′′の2つにしておきます。このようにすると、プログラム動作開始時に1回情報取得、次に14:32になったら自動的に取得、さらに14:34になったらもう一回自動的に取得します。情報取得時にはデバッグ用に次に取得する時刻を表示するようにしていますが、14:34の取得時には、次の取得時刻は翌日の14:32になっているはずです。これが確認できればプログラム動作としては問題ないと思います。セットする(翌日処理に注意)?>PHPで指定時刻に情報更新するプログラムを作成これで、次に取得する時刻を求めることができましたので、本番プログラムに実装してみます。デバッグ用に68行目、97行目、140〜142行目に取得時刻情報を表示するようにしています。LED制御ループは10回繰り返すようにしています。出かける前などに最新の情報を知りたいこともあります。そこで、スイッチが押されたら鉄道運行状況情報のみを更新するようにしたいと思います。天気予報はそれほど変わることはないと思いますので、天気予報情報はあらかじめ設定した時刻になったら取得するようにします。変更点は少ないので、上のプログラムに対して、変更箇所のみ記載します。GPIO18番ピンをスイッチに接続していますので、GPIO18を入力に設定します。GPIOピン設定している部分がありますので、そこにスイッチの設定を追加します。以下の7〜8行目を追加します。in`;[/php]次にスイッチが押されたかの判定ですが、ちょっと感度は悪そうですが、0.25秒ウエイトするところに追加してみます。ここに追加すると、0.25秒ごとにスイッチ状態を確認することになりますので、スイッチを押している時間が短いと、この判定にかからない可能性があります。1秒間に4回スイッチ状態をチェックするので、普通にスイッチを押すのであれば、特に大きな問題はないと思います。LED制御ループない、以下のコードを追加します。