机の上においたボタンを押すとリアルタイムでSlack上に寿司を食べたいことを通知できるシステムを構築した
机の上においたボタンを押すとSlack上に寿司を食べたいことを通知できるシステムを構築した。
動機
寿司を食べたい時にそれをSlackで報告するためわざわざキーボードに手を伸ばすのは非常に面倒である。机の上に専用のスイッチがありそれを押すだけで寿司が食べたいことを通知できれば非常に素晴らしいユーザー体験が得られるはずだ。昔遊んでいたArduinoが家にあったので、それとSlackを組み合わせることでシステムを構築していく。
作り方
Arduino側
100均に行ってボタンっぽいものを購入する。
スイッチ式のシーリングライトがあったので流用。ライトなので押すと光る。
(光る)
気合で内部のスイッチを見つけ出して配線。
内部を開けるとこんなかんじになっていた。緑と黄色のリード線は自分で結線した。
適当に抵抗を繋いでやばい電流がArduinoにいかないようにする。 回路図を示したいところだが、そもそも100均ボタン側の回路が不明なのでプレッドボード側も勘で配線した。 とりあえず5Vを直接グラウンドに繋いではいけないことがわかった。
Arduinoにコードをデプロイ。
const int SWITCH = 2; void setup() { pinMode(SWITCH, INPUT); Serial.begin(9600); } void loop() { if (digitalRead(SWITCH) == HIGH) { Serial.print("1\n"); } else { Serial.print("0\n"); } delay(500); }
Arduinoに繋いでシリアルモニタでチェック。"1"と"0"がボタンに応じて出力されていればOK
。出てなかったら配線とか抵抗を見直す。
Python側
PySerialというモジュールがあるので、それをpipでインストール(Arduinoとの通信)。
こちらを参考にした。
slackwebというモジュールがあるので、それをpipでインストール(Slackとの通信)。
SlackのIncoming WebHookを用いた。異常に簡単にSlackにメッセージを流せる。
Slackにincoming webhook経由でpythonからメッセージをPOSTする - Qiita
コードはこちらを参考にした。 Incoming WebHookのURLは環境変数に格納し、実行時に読み込むようにした。
pythonを実行
import slackweb import os import serial import time url = os.environ["SLACK_OHA"] slack = slackweb.Slack(url=url) port = "/dev/cu.usbmodem1421" current_oha_state = False # ボード側は500ms間隔でserialにHIGH -> b"1", LOW -> b"0"を送信する with serial.Serial(port=port, baudrate=9600, timeout=1) as ser: while True: # time.sleep(0.1) flag = ser.readline() # switch ON if (bytes(b"0") in flag and not current_oha_state): current_oha_state = True print("oha") slack.notify(text="スシ食べたい🍣") # switch OFF elif (bytes(b"1") in flag and current_oha_state): current_oha_state = False print("otu") slack.notify(text="スシいらない🍣") print(flag, current_oha_state)
結果
とりあえずボタンをポチポチ押す。すると、
ほぼリアルタイムでこのようになる。ギリギリIoTの範疇に入る気がする。
これで快適に他人にスシを食べたいことを通知できるようになった。 会社のCTOがArduinoの無線モジュールを入手したようなので、それを使えばボタンをPCから独立させることも可能な気がする。未来っぽい。
最急降下法をPythonで実装した
関数x2 + xは、どうやら最小値がひとつだけ存在するらしい。どうしてもその値を知りたくなったので、最急降下法を使ってPythonでその値を求めてみた。
#!/usr/bin/env python # -*- coding: utf-8 -*- import random learning_late = 0.01 loop_max = 1000 def main(): initial = random.uniform(-10, 10) old = initial new = 0.0 for _ in range(1000): # 更新式 new = old - learning_late * diff_func(old) # 目的関数の値を確認 y = object_func(new) print(y) # 値を更新 old = new print(new, y) # 目的関数 def object_func(x): return x * x + x # x ^ 2 + x の微分 def diff_func(x): return 2 * x + 1 if __name__=='__main__': main()
これを実行すると、
# x、y (-0.5000000145792641, -0.24999999999999978)
と、xが-0.5付近の時に目的の関数が最小値となることがわかった。なるほどというかんじ。
- 作者: 中井悦司
- 出版社/メーカー: 技術評論社
- 発売日: 2015/10/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
- 作者: 高村大也,奥村学
- 出版社/メーカー: コロナ社
- 発売日: 2010/07
- メディア: 単行本
- 購入: 13人 クリック: 235回
- この商品を含むブログ (41件) を見る
新年になったのでGIF作成webアプリ「にこ☆GIF」をmp4に対応させた
正月休み中暇だったので、ニコニコ動画からGIFを作成するツール「にこ☆GIF」をmp4に対応させた。
どんなかんじか
例えばこんな動画をGIFに変換すると、
となる。
実装について
基本、ffmpegで動画ファイルをGIFに変換するだけなのだが、なにも考えずに行うと動画をいちいち全て取得する必要があって、異常に時間がかかっていた。
そこで、動画の途中からデータを部分的に取得するように実装したのだが、そのようにすると動画として再生できないバイナリの断片しか得られない。そこで、pythonを使って力技でファイルの断片から.264ファイルを擬似的に作成して、それをffmpegでmp4に変換することにした。mp4と.264、仕様書は存在するのだが、英語が全然読めなくて非常に辛かった。結局はmp4のバイナリを目で読んで仕様をバイト列から類推するみたいなかんじになった。一年分はバイナリエディタを使ったと思う。当分16進は見たくない。
参考にしたもの
https://www.cmlab.csie.ntu.edu.tw/~cathyp/eBooks/14496_MPEG4/iso14496-10.pdf
太宰治小説のTF-IDFを計算した
を参考に、太宰治小説のTF-IDFを計算した。以下、値が上位のものから単語だけ30個並べると、
いちど,謂わ,依っ,要ら,つらい,やたら,ご存じ,在っ,先日,おそろしく,だいいち, あがっ,ゆるし,下さっ,おそろしい,落ちつき,青森,あいだ,くるしい,おそく,ちかく, おまえ,ごはん,大笑い,具合い,判ら,ちまい,のこのこ,としの,三鷹,やけくそ,たいてい, れい,だめ,無かっ,ちゃんと,逢う,津軽,あらわれ,繰りかえし,わびし,あれこれ,わかい, うつむい,みじん,いやらしい,わがまま,ふるさと,於い,在る,口調,なんにも,捨て, 無学,ッ,なさっ,だいたい,概念,判る,長兄,生家,安易,素知らぬ,金木,したため,熱狂, あいそ,のろのろ,ごちそう,わるい,芸術,ばん,之,落ちつい,まじめ,ことし,敗北,自重, たのしみ,めいわく,長編,ロマンス,かたち,悪癖,言える,記さ,あからめ,知合い,滅茶, とたんに,あやしい,心掛け,判っ,くさく,高潔,まごつい,侘び,あたらしく,甲府,ひくく, むだ,瞬時,ふっと,酔っ,大 声,きらい,内心,おのれ,ゆえ,ふたり,おめでとう
のようになる。ネガティブな単語が多く含まれていて、非常に満足度が高い。
https://github.com/soy-curd/Dazai/blob/master/doc/flayer.png
ついでに文学フリマ用のビラもできたので、ひと安心。
小説風文章生成アプリ『Bungoo』を少し改造した
今までは小説のデータを取ってくるのに毎回毎回青空文庫からデータを引っ張ってたのだけれど、 さすがにDosアタックしてるような気持ちになったので、PostgreSQLにデータを全部突っ込んでそこからデータ取るようにした。
ついでに、markov chainを作るのにめちゃくちゃ時間がかかっていたので、それもあらかじめ作成してpickle.dumpsしてデータベースに格納した。これで高速化できるはずだったけど、調子に乗って太宰治の小説を200本くらいポスグレにいれたせいで文字列を作るほうで時間かかってしまい差し引きゼロになった。むしろ遅くなったかもしれない。残念。
文學ラボに同人誌の原稿追加した
python用のシリアライザmarshmallowで辞書オブジェクトとJSONの相互変換
pythonのシリアライザであるmashmallowを業務で使うことになったのでメモ。
はじめに
webアプリケーションを作成していると、
{ 'hoge':'1', 'foo':'2', 'bar':3 }
のような辞書オブジェクトを、
'{"foo": "2", "hoge": "1", "bar": 3}'
のようなJSONに変換したい場合(やその逆)がある。その時に使えるのが、marshmallowである。
インストール
pip install marshmallow
でOK。
簡単な例
まず、marshmallowを使うには、スキーマというものを定義する必要がある。
たとえば上の例だったら、以下のように定義する。
# スキーマを定義 class HogeSchema(Schema): hoge = fields.Str(required=True) foo = fields.Str(required=True) bar = fields.Int(required=True)
これを使うと、
hoge_data = { 'hoge':"1", 'foo':'2', 'bar':3, } data, err = HogeSchema().dumps(hoge_data) pprint(data) pprint(err) # '{"foo": "2", "hoge": "1", "bar": 3}' # {}
というふうにJSONに変換することができる。
逆の場合は、
hoge_data = '{"hoge":"1","foo":"2","bar":3}' data, err = HogeSchema().loads(hoge_data) pprint(data) pprint(err) # {'bar': 3, 'foo': '2', 'hoge': '1'} # {}
として、loadsを用いるとJSONストリングを辞書オブジェクトに変換できる。
なお、marshmallowはバリデーション機能も持っているので、さきほどのスキーマを用いて、
hoge_data = '{"hoge":"1","foo":"2"}'
のようなフィールドの不足したデータをデシリアライズしようとすると、
# {'bar': ['Missing data for required field.']}
と、エラー理由を戻り値に格納してくれる。
応用
marshmallowであるが、フィールドを拡張することで、各フィールドの値を好きなように変換することもできる。例えば、
class IppaiHogeHoge(fields.Field): def _serialize(self, value, attr, obj): if value == "1": return value * 10 else: return value class HogeSchema(Schema): hoge = IppaiHogeHoge(required=True) foo = fields.Str(required=True) bar = fields.Int(required=True)
のように定義すると、dumpした結果は、
data, err = HogeSchema().dumps(hoge_data) pprint(data) pprint(err) # '{"foo": "2", "hoge": "1111111111", "bar": 3}' # {}
のようにできるので便利。
おわりに
上の方法とは別に、JSON -> class変換はmarshmallowでできるようなのだが、 class -> JSON変換の方法がまだわからないので、もう少し調べる。。。
- 作者: 株式会社ビープラウド
- 出版社/メーカー: 秀和システム
- 発売日: 2015/05/21
- メディア: Kindle版
- この商品を含むブログを見る