メモブログ

やったことを少しでも残すブログです

LightsailのLAMP環境メモ

各Serviceの確認と再起動の方法

Start or stop services
各サービスのステータス

sudo /opt/bitnami/ctlscript.sh status

apache の再起動

sudo /opt/bitnami/ctlscript.sh restart apache 

Apatchログの確認方法

以下のコマンドで確認できる。

tail /opt/bitnami/apache/logs/error_log
tail /opt/bitnami/apache/logs/access_log

Raspberry pi pico w を使って現在時刻を設定/取得する。。。

raspberry pi pico wを使ってJSTを取得するプログラムを書いた。
本来の目的として、raspberry pi pico w -> sshAmazon Lightsailにアクセスし、DBにデータを突っ込む!っということをしたかったのだが、raspberry pi picoにはOSが無いことをすっかり忘れてしまっていた。
raspberry pi picoからsshを用いて他の環境へアクセスはできない。。。httpサーバーにはなるので、httpリクエストを捌くことはできるが、他の環境へアクセスができないと思っています。
GPTさんもそのような回答。。。(以前にも調べたができないことをすっかり忘れていた)
せっかく作ったので以下を記載。

import network
import usocket as socket
import ustruct as struct
import utime
from machine import RTC
import time

# Wi-Fiに接続する関数
def connect_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    print("testssss")
    wlan.connect(ssid, password)
    
    # Wi-Fi接続が完了するまで待機
    while not wlan.isconnected():
        pass
    print('Wi-Fi connected:', wlan.ifconfig())

# NTPサーバーから時刻を取得する関数 (ntp.nict.jp を使用)
def get_ntp_time():
    NTP_DELTA = 2208988800  # NTPタイムスタンプの1970年とのオフセット(秒)
    host = "ntp.nict.jp"  # 日本のNTPサーバー
    
    # NTPサーバーに接続
    addr = socket.getaddrinfo(host, 123)[0][-1]
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(1)
    
    # NTPリクエストパケットを作成(48バイトのリクエスト)
    msg = b'\x1b' + 47 * b'\0'
    s.sendto(msg, addr)
    
    # レスポンスを受け取る
    msg, _ = s.recvfrom(48)
    s.close()
    
    # NTPタイムスタンプを抽出(秒単位)
    val = struct.unpack("!I", msg[40:44])[0]
    print(val)
    
    # Covert To JST
    return val - NTP_DELTA + 9*60*60
    
# RTCにNTPサーバーから取得した時刻を設定する関数
def set_time():
    t = get_ntp_time()
    tm = utime.localtime(t)
    
    # RTCに設定
    rtc = RTC()
    rtc.datetime((tm[0], tm[1], tm[2], tm[6], tm[3], tm[4], tm[5], 0))

    # 現在の日時を表示
    print('現在時刻: UTC', rtc.datetime())

参考にさせていただいたページ
Pi Pico W を単体起動後、NTPサーバーに接続して時刻を取得 – FRONT
utime -- 時間関連の関数 — MicroPython 1.13 ドキュメント
utime -- 時間関連の関数 — MicroPython 1.13 ドキュメント

やりたいことを実現するには、大人しくRaspberry piRaspberry pi Zero 2 Wを使うとするか。。。

Amazon Lightsail に Tomcat を入れてみた

Amazon Lightsail に Tomcat を入れてみた。

構成

手順

  1. Tomcatのインストールマニュアルに従ってJDKをインストール
  2. Apache Tomcatをインストールし$CATALINA_HOMEと$JRE_HOMEを設定
  3. Tomcatを起動し、http://localhost:8080/ へアクセスし、起動しているか確認

困ったこと

解決策

  • 自身のWindowsマシンでPuTTYgenを使ってPrivate Keyをppk形式にする必要がある。単に以下の手順に従ってpemファイルをLoadすれば良い。
  • Generateし直さないこと!!!
  • PuTTYの設定を以下のようにすればトンネルが開通することができた。自分のローカルホストと、Lightsail のローカルホストが繋がった?と思われる。
  • ポイント
    • Source Port -> 8080 <--- 使用するマシンのポート(自分のPC)
    • Destination - localhost:8080
PuTTY

Tomcat へアクセス

サンプルも表示することができた。
これからJSP/Servletのお勉強を頑張ります。自分のPCでサーバーを立ててお勉強するのも良いのだが、せっかくなので、Lightsail に環境を構築してみた。

Sample

NFLの試合結果を記録するページと結果を表示するページを作成した

NFLの試合結果を記録するページと結果を表示するページを作成した。2023年のNFLも全力で楽しむために!
(Week 1 が終わったが・・・ロジャースさん。。。マジかよ。。。推しチームの危機っす。。。早くも。。。)

NFLのファンである私は、同一週に複数の試合を見て楽しんでいる。
好きなチームの試合も観るが、勢いのあるチーム、連勝が続いているチームの試合を見たい。そのため、試合結果を確認する必要がある。
しかしながら、公式ページを見てしまうと、既に今週の試合結果も載ってしまっていることが多く、自分のペースで試合結果を記録したかった。
(迂闊にFacebookを開いたり、公式ページを開くと直ぐに結果が見れてしまうため、興ざめてしまう...)

NFLの試合結果を入力し、SQL文を生成するページを作成!

APIで結果を取得したかったが、公式の無料APIは無く、パートナー契約をする必要があったので断念。スクレイピングをやれば出来るじゃ?っとも思ったが、上手くいかず、時間もなかったので断念。
クラウド環境においてそのままDBに挿入させても良かったが、セキュリティをつける必要があり(一応)、時間的に余裕が無いのでローカルでSQL文を生成 -> コピペで挿入。っという方法を採用。


構成

工夫したところ

  • 32チームの結果を手動入力するため、入力ミスを出来るだけ減らしたかった。
  • そのため、選択したチームは値リストから減らし、HTMLの要素を再生成する方法を取った。

コーディング

  • Map を使ってリストを作成し、値リストを生成する
let teamList = new Map()
teamList.set("SF", "49ers");
teamList.set("CHI", "Bears");
teamList.set("CIN", "Bengals");
teamList.set("BUF", "Bills");
teamList.set("DEN", "Broncos");
teamList.set("CLE", "Browns");
teamList.set("TB", "Buccaneers");
teamList.set("ARI", "Cardinals");
  • 選択したチームをリストから削除し、selectの要素を再生成する
function recreateSelectValues(caller) {
    let winner = document.getElementById("winner");
    let loser = document.getElementById("loser");
    
    let draw1 =document.getElementById("draw1");
    let draw2 = document.getElementById("draw2");

    let byeWeek = document.getElementById("byeWeek");
    
    if (caller === "winORlose") {
        // remove win team and lose team from map
        teamList.delete(winner.value);
        teamList.delete(loser.value);
    } else if (caller === "byWeek") {
        // remove bye week from map
        teamList.delete(byeWeek.value);   
    } else if (caller === "draw") {
        // remove draw teams from map
        teamList.delete(draw1.value);
        teamList.delete(draw2.value); 
    }

    
    // 
    let currenWinterTean = winner.childElementCount;
    for (let i = 0; i < currenWinterTean; i++) {
        winner.children[0].remove();
        // console.log(i);
    }

    let currenLoserTean = loser.childElementCount;
    for (let i = 0; i < currenLoserTean; i++) {
        loser.children[0].remove();
    }

    let currenDraw1Tean = draw1.childElementCount;
    for (let i = 0; i < currenDraw1Tean; i++) {
        draw1.children[0].remove();
    }

    let currenDraw2Tean = draw2.childElementCount;
    for (let i = 0; i < currenDraw2Tean; i++) {
        draw2.children[0].remove();
    }


    let currenTean = byeWeek.childElementCount;
    for (let i = 0; i < currenTean; i++) {
        byeWeek.children[0].remove();
        // console.log(i);
    }

    // generate team values again.
    generateTeamsValues();
}

-- select 要素の子要素を再生成する
function generateTeamsValues() {
    teamList.forEach(function (value, key, teamList) {
        let op = document.createElement("option");
        op.value = key;  
        op.text =value;   
        op.className = "teamList";
        document.getElementById("winner").appendChild(op);
    })
.....

試合結果を各ディビジョン毎に表示させるページを作成!!

phpmySQL にアクセスして取得する。
もう少し、weekが進んだら画面ショットを張る予定。

開発環境

  • XAMMP.
  • Apacheのデフォルトの設定では、 xampp -> htdocs 以下にファイルを置く必要あったので、こちらにディレクトリを作成し、コーディングして行った。
  • エディタは、Visial Stadio Codeを採用。

本番環境

mySQLでは、SQL結果セットをクローズしないと、次のSQLを実行できないらしい(?)ので、その点を気を付けた。

PHP: mysqli::query - Manual

/* 注意: 全てのレコードが取得されるか、結果セットがクローズされるまで
サーバーとやりとりを行うあらゆる関数は実行できません。あらゆる呼び出しは
'out of sync' を返します */
mysqli_query($link, "SET @a:='this will not work'");

こんな感じ。

<?php
function generate_week_record($year, $mysqli){
    // Get Max Week Number
    $sql = "SELECT MAX(WEEK) FROM team_result where YEAR = ".$year;
    $result = $mysqli->query($sql);
    $NUMBER_OF_WEEK = 0;
    if ($result = $mysqli->query($sql)) {
        // Get results
        while ($row = $result->fetch_assoc()) {
            $NUMBER_OF_WEEK = $row["MAX(WEEK)"];
        }
        // Close results set
        $result->close();
    }
    $Header = null;
    for ($i = 1; $i <= $NUMBER_OF_WEEK; $i++) {
        $Header = $Header."<td>"."Week ".$i."</td>";
    }
    echo  "<tr>"."<td>Team</td>".$Header."</tr>"."\n";
}

学んだこと&感想

  • 自身としては初めてjavascriptを使った。javascriptの本は数冊読んだが、一からコーディングするのは初めて。慣れない所も多かったが楽しかった。
  • 特にHTMLは静的であるため、これを扱うことに苦労した。何で初期化されないの?ループさせているんだが、上手くいかないな・・・?っということがあった。
  • フロントエンドの開発も楽しい。
  • 今更ながらXAMMPの使い方が分かったw XAMMP素晴らしいっす。。。笑
  • サーバーサイドは、javaを使いたかったが、自身のLightsail環境は最安の環境であるため、メモリ不足の可能性があった。
  • javaでもアプリ作成を頑張りたいが、、、次は何を作ろうか。。。

Raspberry Pi Pico W で温度と湿度を図ってみた

Raspberry Pi Pico W で温度と湿度を図ってみた。

出来たこと

温度と湿度を図り、スマホやPCからデータをWEB経由で確認できるようになった。


用意したもの

アプローチ

  1. Raspberry Pi Pico WとDHT11を繋ぎ、検知したデータを取得できるようにした。
  2. Raspberry Pi Pico Wをhttpサーバーにした。
  3. ローカルPCからPicoに温度と湿度を図るようリクエストをあげる
  4. ローカルPCからLightsailにあるMySQLにデータを突っ込む
  5. LightsailのApacheにファイルを置いてMySQLからデータ取得、HTML生成
    • Apatchのデフォルトの設定についていい感じのページがあったのだが、忘れてしまった。。。残念。

コード

getTempAndHumi()を作成し、データを取得し、jsonで返すようにしてみた。

def getTempAndHumi():
    d = dht.DHT11(machine.Pin(15))
    try:
        sleep(1)
        d.measure()
        print("test")
    except OSError as e:
        print(e.errno)
        print('Faild')
        
    data = {
        "temperature": str(d.temperature()),
        "humidity" : str(d.humidity())
    }
    return data

"""
/ 色々と書いて
"""
# Listen for connections
while True:
    try:
        cl, addr = s.accept()
        print('client connected from', addr)
        cl_file = cl.makefile('rwb', 0)
        while True:
            line = cl_file.readline()
            if not line or line == b'\r\n':
                break
        cl.send('HTTP/1.0 200 OK\r\nContent-type: application/json\r\n\r\n')
        data = getTempAndHumi()
        json_data = json.dumps(data).encode('utf-8')
        cl.send(json_data)
        cl.close()
    except OSError as e:
        cl.close()
        print('connection closed')

何故かPico単体で動かないことがあった。どこで処理が落ちているか分からなかったので、無理やり、LEDが点滅するかどうかをブレイクポイントにしました。
もっといい方法があったはず。

led = machine.Pin("LED", machine.Pin.OUT)
while True:
    led.on()
    utime.sleep(1)
    led.off()
    utime.sleep(1)

学んだこと

  • Lightsailの環境にアクセルするには、プライベートキーが必要。
  • LightsailのLAMPへアクセスするには、SSHトンネルを使う必要がある。
  • 現状のPico はOSを持たない(マイコン)なので、SSHトンネルを設定できない。
  • MicroPythonは少し癖がある印象。Pythonではできることが、MicroPythonではできない場合がある。特にパッケージはMicroPython用のパッケージがないと動かない。
  • OSがあるって何て素晴らしいことなのだろうか!!!