土用の丑の日は終わってしまいましたが、
— 多岐川ノリ@ぼっち系プログラマー (@n2_taki) July 20, 2020
スーパーで580で中国産のうなぎが売られていましたので、
上の方法で調理してご飯と一緒に頂きました。
これはね、うなぎがめっちゃ柔らかくなります。
レンチンしたうなぎとは全然違います。
箸で身が簡単に裂くことが出来ます。
これは完全に、直前まで厨房で焼いていましたといううなぎ。
これはみんな是非試して欲しい。
スーパーの安いうなぎも美味しく食べられます。

土用の丑の日は終わってしまいましたが、
— 多岐川ノリ@ぼっち系プログラマー (@n2_taki) July 20, 2020
スーパーで580で中国産のうなぎが売られていましたので、
上の方法で調理してご飯と一緒に頂きました。
これはね、うなぎがめっちゃ柔らかくなります。
レンチンしたうなぎとは全然違います。
箸で身が簡単に裂くことが出来ます。
これは完全に、直前まで厨房で焼いていましたといううなぎ。
これはみんな是非試して欲しい。
スーパーの安いうなぎも美味しく食べられます。

前回までの状況はこちら。
ラズパイにHTTPサーバを実装したので、今回はHTTPクライアントをWindowsに作成します。
以前こちらで作成したのは、HTTPサーバですが、基本的にはこれを流用します。
なので、ソースコードはほとんど似ています。
違いはサーバ処理しているところをクライアント処理しているところぐらいです。
<Window x:Class="IroiroMonitor.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="温度" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" Width="239" Height="86" FontSize="48"/>
<Label Grid.Row="1" Grid.Column="0" Content="湿度" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48" Margin="10" Width="239" Height="87"/>
<Label Grid.Row="0" Grid.Column="1" Content="{Binding Temperature}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48"/>
<Label Grid.Row="1" Grid.Column="1" Content="{Binding Humidity}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48"/>
</Grid>
</Window>
namespace IroiroMonitor
{
[JsonObject("sensorModel")]
public class Sensor
{
[JsonProperty("datetime")]
public string datetime { get; set; }
[JsonProperty("temperature")]
public string temperature { get; set; }
[JsonProperty("humidity")]
public string humidity { get; set; }
}
}
namespace IroiroMonitor.ViewModels
{
public class MainWindowViewModel : BindableBase
{
private string _title = "いろいろ計測モニター";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private double _temperature;
private double _humidity;
public double Temperature
{
get { return _temperature; }
set { SetProperty(ref _temperature, value); }
}
public double Humidity
{
get { return _humidity; }
set { SetProperty(ref _humidity, value); }
}
public MainWindowViewModel()
{
Thread thread = new Thread(new ThreadStart(async () => {
try
{
HttpClient client = new HttpClient();
while (true)
{
HttpResponseMessage response = await client.GetAsync("http://192.168.1.15:8000/");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Sensor sensor = JsonConvert.DeserializeObject<Sensor>(responseBody);
double temp = 0;
double hum = 0;
double.TryParse(sensor.temperature,out temp);
double.TryParse(sensor.humidity, out hum);
Temperature = temp;
Humidity = hum;
Thread.Sleep(1000);
}
}
catch (Exception ex)
{
}
}));
thread.Start();
}
}
}

Microsoft社員のちょまどさんが所有しているPixel3のバッテリーが膨張したという話を聞いて。
Google Pixel 3 、
— ちょまど🎀 (@chomado) July 27, 2020
とても好きで毎日使ってて、
で、すごく熱くなることが多くて
ふとスマホケースを外してみたら
バッテリーが膨張してた😲 pic.twitter.com/QTVdUB4C7x
スマホに負荷をかけ続けていると、その負荷がバッテリーにもかかり、結果的にバッテリーに損傷を与えます。(バッテリー膨張という形で)
ちょっと前だったらiPhoneでよく見られた現象ですが、Androidでも起きるんですね。
最近のスマホって、PC並みの性能を持っている一方で、PCでは当たり前のCPUファンがスマホでは実装できない、という弱点を持っているのですよ。
なので、スマホ延命策の基本として、
熱いと思ったら自然放熱を待つ
というのが、基本的なスマホの発熱ケアと言えます。
この間、スマホの操作も、スマホの充電も禁止です。
スマホの充電は、その行為だけでバッテリーは熱を発しますし、最近のスマホゲームはCPUパワーを大量に使いますので、熱を発します。
なので、スマホが熱いと思ったら、熱が収まるまで放置するのが最善です。
特に、スマホケースを使用している方は、スマホケースによって放熱を阻害しているので、すぐにケースから外したほうがいいです。
ちょまどさんみたいに、「あったかーいホッカイロみたい」と思っていてはダメです。
さらに付け加えるとすると、
スマホが熱いからと言って、冷蔵庫や冷却剤などで強制的に冷却するのもNGです。
強制的に冷却すると、スマホの内部で結露し、スマホ基板自体が損傷する可能性があります。
これは防水機能の有無とか関係なく起こります。
じゃあ、どうするのが一番良いのかというと、自分が考えるのはスマホクーラーなどで風を送り続けて冷やすことです。
この方法ならば、結露すること無く、スマホを効率よく冷やすことが出来ます。
ちなみに、
オイラはPixel3を手帳型スマホケースに入れて使用していますが、自宅に帰ると、すぐにスマホケースから外して、スマホクーラーの風に当ててます。
その甲斐もあって、オイラのPixel3は未だにバッテリー膨張することなく、未だに現役で使い続けることが出来ます。
今持っているスマホを少しでも長く使いたいならば、スマホクーラーを使用することも一つの案です。
最近のスマホクーラーはサイズも小さくて良いっすね。
(オイラは一世代昔のスマホクーラー使用)
前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/diet-mng
データ入力処理ですが、すでにデータ入力画面や一連の処理は作成してあるので、同じ要領でデータ詳細画面にもデータ入力画面への導線を作成します。
EatingDetailComponent.vue
<template>
<-- 中略 -->
<p id="inputbutton">
<button @click="onClickInput">データ入力</button>
</p>
<-- 中略 -->
<eating-input-dialog-component :show="showInputDialogContent" :date="date" :datehold=false @update="invokeUpdateList"></eating-input-dialog-component>
<-- 中略 -->
</template>
<script>
export default {
//中略
methods: {
onClickInput: function() {
this.showInputDialogContent = true;
},
invokeUpdateList: function() {
this.updateList();
},


前回までの状況はこちら。
最新ソースはこちら(gitHub)
https://github.com/takishita2nd/AroundHokkaido
さて、前回作成したJsonファイルを、実際にAndroidアプリに読み込ませるのですが、
こちらの記事を参考にさせて頂きました。
https://qiita.com/Bluewind1997/items/c3f8e90e9fb19f47daee
assetsフォルダを作成して、その下にJsonファイルを作成して設置します。
あとはassetManagerを介せば、そのJsonファイルにアクセス出来ます。
ただ、assetManagerが使えるのはMainActivityだけ。
Androidのプログラミングでは、このMainActivityが重要でして、
Androidに関する重要な処理は、このMainActivityが無ければ使用できません。
なので、どこからでもMainActivityを使用できるように、シングルトンにしてしまえば良いのではと思いましたが、
Kotlinにはシングルトン(というか、staticクラス)という概念がないので、
ここだけJavaで書きました。
package com.takilab.aroundhokkaido;
import androidx.appcompat.app.AppCompatActivity;
public class SingletonActivity {
private static AppCompatActivity _activity;
public static void SetActivity(AppCompatActivity activity) {
_activity = activity;
}
public static AppCompatActivity GetActivity(){
return _activity;
}
}
JavaとKotlinは混在できるんですね。
実際の開発現場では、どのようにMainActivityを扱っているんですかね?
このMainActivityを使ってJsonの読み出し。
package com.takilab.aroundhokkaido
class City(city: String, distance: Double) {
val city: String = city
val distance: Double = distance
}
package com.takilab.aroundhokkaido
import org.json.JSONException
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStreamReader
class CityList {
val cityList: ArrayList<City> = ArrayList()
init{
val activity: MainActivity = SingletonActivity.GetActivity() as MainActivity
val assetManager = activity.resources.assets //アセット呼び出し
val inputStream = assetManager.open("AroundHokkaido.json") //Jsonファイル
val bufferedReader = BufferedReader(InputStreamReader(inputStream))
val str: String = bufferedReader.readText() //データ
try {
val jsonObject = JSONObject(str)
val jsonArray = jsonObject.getJSONArray("list")
for (i in 0 until jsonArray.length()) {
val jsonData = jsonArray.getJSONObject(i)
val city: City = City(jsonData.getString("city"), jsonData.getDouble("distance"))
cityList.add(city)
}
} catch (e: JSONException) {
e.printStackTrace()
}
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
SingletonActivity.SetActivity(this);
val cityList = CityList()
for (city in cityList.cityList) {
Log.d("Check", "${city.city} : ${city.distance}")
}
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 札幌 : 35.9
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 小樽 : 20.1
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 余市 : 15.9
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 古平 : 6.4
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 積丹 : 49.0
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 神恵内 : 6.3
2020-08-07 09:02:07.564 6520-6520/com.takilab.aroundhokkaido D/Check: 泊 : 17.9
:
:
それは気がつかなかった。
https://store.google.com/jp/product/pixel_buds?hl=ja-JP

ぶっちゃけ、Sony WF-SP800Nで十分満足しているのですが。
仕様を比較すると、WF-SP800Nに搭載されているGoogle Budsはノイズキャンセリングが無い。
その代わり、耳に完全にフィットさせることでノイズを遮断、空気孔で周辺の音を聞こえやすくしているらしい。
WF-SP800Nは左側タップでAlexaを起動できますが、Google Budsは声でGoogleアシスタントを起動できるらしい。
起動もハンズフリーなのはイイネ👍
Google Budsはスマートフォンと連携して自動翻訳機能があるらしい。使う機会は少ないと思うけど。
Google Budsは無線充電に対応しているのもイイネ👍
防水機能も付いているので、スポーツにもイイネ👍
WF-SP800Nを使っているときも思ったけど、声だけでプレイリスト再生出来るの、すごい便利よ。

最新ソースはこちら(gitHub)
https://github.com/takishita2nd/HokkaidoWar
以前作成したこれ。

これの「敵の行動」の部分を作成していきます。
敵を行動させるのであれば、すでに作成済みである、
class Battle
{
public void NextTurn()
を実行すればいいでしょう。
では、次の状態遷移の条件である、「自分の都市の順番が来た場合」を考えます。
それを行うには、自分の都市と、次に実行する都市をBattleクラスから取得する処理があればいいでしょう。
class Battle
{
public City GetActionCity()
{
return _cities[cityCnt];
}
class Player
{
private City _city;
public City City { get { return _city; } }
public Player(City city)
{
_city = city;
}
}
class HokkaidoWar
{
public void Run()
{
// 中略
while (asd.Engine.DoEvents())
{
asd.Vector2DF pos = asd.Engine.Mouse.Position;
switch (gameStatus)
{
// 中略
case GameStatus.ActionEnemy:
if (_player.City.Equals(_battle.GetActionCity()))
{
gameStatus = GameStatus.ActionPlayer;
}
else
{
Thread.Sleep(100);
_battle.NextTurn();
}
break;
}
if (asd.Engine.Mouse.LeftButton.ButtonState == asd.ButtonState.Push)
{
// 中略
switch (gameStatus)
{
case GameStatus.ActionEnemy:
break;
}
}
asd.Engine.Update();
マウスクリック処理は特にやることがないので、何もやる必要はありません。
すいません、
昨日のこれ、修正します。
何が問題なのかというと、複数のスレッドが同じデバイスにアクセスしている、と言うことです。
デバイスにアクセスするときには「一連のアクセス処理」が発生します。
温湿度計にアクセスする場合は、I2Cインターフェースを使用しているので、データの要求・応答に2つの端子にパルスパターンを送受信しているはずです。
この処理を複数のスレッドで同時に行った場合、正しくアクセス処理が行われない場合があります。
アクセス処理が競合しちゃうんですね。
これを防ぐために、こういったマルチスレッドのプログラミングでは「待ち合わせ処理」(一方の処理が完了するまで、もう一方の処理を待つ)というのが必要なのですが、
今回は規模が小さいので、アクセスを行うスレッドを一つだけ(メインのスレッドのみ)にして、他のスレッドからはデバイスにアクセスしないようにします。
Humidity = 0
Temperature = 0
def __main__():
global sw
global Humidity
global Temperature
GPIO.setmode(GPIO.BCM)
GPIO.setup(22,GPIO.IN)
GPIO.add_event_detect(22, GPIO.FALLING, callback=callback, bouncetime=300)
GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
GLCD.GLCDInit()
GLCD.GLCDDisplayClear()
roop = 10 * 60 * 60
mode = 1
thread = threading.Thread(target=httpServe)
thread.start()
try:
while True:
Humidity = AM2320.GetHum()
Temperature = AM2320.GetTemp()
if sw == True:
GLCD.GLCDDisplayClear()
mode += 1
if mode > 4:
mode = 1
sw = False
if mode == 1:
if roop >= 10 * 60 * 60:
GLCD.GLCDDisplayClear()
Weather.RequestAPI()
weather = Weather.GetWeather()
temp = Weather.GetTemp()
roop = 0
GLCD.GLCDPuts(1, 0, "Date :")
GLCD.GLCDPuts(5, 8, datetime.datetime.now().strftime('%Y:%m:%d %A '))
GLCD.GLCDPuts(1, 16, "Weather :")
GLCD.GLCDPuts(10,24, weather)
GLCD.GLCDPuts(10,32, "Temp : " + format(temp) + 'C')
GLCD.GLCDPuts(1, 40, "Time : " + datetime.datetime.now().strftime('%H:%M'))
GLCD.GLCDPuts(1, 48, "Humidity : " + Humidity + '%')
GLCD.GLCDPuts(1, 56, "Temperature : " + Temperature + 'C')
roop += 1
#中略
time.sleep(1)
except KeyboardInterrupt:
GLCD.GLCDDisplayClear()
GPIO.cleanup()
#中略
class StubHttpRequestHandler(BaseHTTPRequestHandler):
server_version = "HTTP Stub/0.1"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def do_GET(self):
enc = sys.getfilesystemencoding()
data = {
'datetime' : datetime.datetime.now().strftime('%Y:%m:%d %H:%M:%S'),
'temperature': Temperature,
'humidity': Humidity,
}
encoded = json.dumps(data).encode()
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", "text/html; charset=%s" % enc)
self.send_header("Content-Length", str(len(encoded)))
self.end_headers()
self.wfile.write(encoded)
__main__()
これで競合は回避できるはず。
測定した温度、湿度をWindows側で表示させたいと思います。
前回HATでやったときはラズパイ側をクライアント、Windows側とサーバとして動作させましたが、
今回は逆で、ラズパイ側をサーバ、Windows側をクライアントとして実行させます。
常に稼働している方をサーバにする方が何かと都合が良い。
こちらの記事を参考にしました。
https://qiita.com/linxuesong/items/8ac98102c24b8f587a16
ただし、このままサーバとして稼働させると、他の処理が出来なくなってしまいます。
なので、HTTPサーバの処理を、既存のループ処理とは別スレッドで実行する必要があります。
なので、スレッドの扱いについて、こちらの記事を参照。
https://qiita.com/tchnkmr/items/b05f321fa315bbce4f77
最終的に組み上がったコードはこちら。
import os
import sys
import urllib.parse
import json
import RPi.GPIO as GPIO
import time
import datetime
import calendar
import GLCD
import AM2320
import Weather
import threading
from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
from http import HTTPStatus
PORT = 8000
sw = False
def __main__():
global sw
GPIO.setmode(GPIO.BCM)
GPIO.setup(22,GPIO.IN)
GPIO.add_event_detect(22, GPIO.FALLING, callback=callback, bouncetime=300)
GLCD.PinsInit(20, 7, 8, 9, 18, 19, 10, 11, 12, 13, 14, 15, 16, 17)
GLCD.GLCDInit()
GLCD.GLCDDisplayClear()
roop = 10 * 60 * 60
mode = 1
thread = threading.Thread(target=httpServe)
thread.start()
try:
while True:
#既存のループ処理
time.sleep(1)
except KeyboardInterrupt:
GLCD.GLCDDisplayClear()
GPIO.cleanup()
def callback(channel):
global sw
sw = True
def httpServe():
handler = StubHttpRequestHandler
httpd = HTTPServer(('',PORT),handler)
httpd.serve_forever()
class StubHttpRequestHandler(BaseHTTPRequestHandler):
server_version = "HTTP Stub/0.1"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def do_GET(self):
enc = sys.getfilesystemencoding()
data = {
'datetime' : datetime.datetime.now().strftime('%Y:%m:%d %H:%M:%S'),
'temperature': AM2320.GetTemp(),
'humidity': AM2320.GetHum(),
}
encoded = json.dumps(data).encode()
self.send_response(HTTPStatus.OK)
self.send_header("Content-type", "text/html; charset=%s" % enc)
self.send_header("Content-Length", str(len(encoded)))
self.end_headers()
self.wfile.write(encoded)
__main__()
Windows側からHTTPのGETリクエストを受信すると、時刻、温度、湿度をJson形式で応答を返します。

今日の北海道は暑いぜ。
こないだ泊まったホテル、GoToキャンペーンでの還付金対象だという事が、チェックイン時に判明しました。
まぁいろいろ問題になっているキャンペーンですけど、
もらえるならもらっちゃおう。
上のサイトに、申し込み方法が書いてあります。
大きく分けて、旅行会社のプランの中にキャンペーン適用されている物と、旅行後に申請する物の2パターンあり、オイラは後者の方です。

必要な書類も上のリンクからダウンロード出来ます。
上にある申請書類の内、②と③はホテルから発行されるものです。無くさないように。
こちらで記入するのは①と④です。
Excelをダウンロードして、記入、印刷して提出です。
あとは、金融口座確認用のコピー(キャッシュカードなど)と、
本人確認用書類のコピー(運転免許証など)を用意すればOK。
ただし、申請の受付は8月14日からなので、まだ送付できません。
宛先も公開されていません。
まずは、8月14日まで待つべし。
ちなみに、実費の半分が還付されますので、オイラの場合は2450円戻ってきます。(少な!)
利用できる制度は利用しようぜ、税金払ってるんだからな!