プログラミング素人のArduino

技術屋の末端。プログラミングは専門外。 電気回路も専門外です。 コードに間違いなど見つけられたら、気軽にコメントください。 VC#、ラズパイ始めました。

クリップボードの中身を取得

以前作ったスクレイピングアプリなのだが、ChromeからURLをコピペして…実行し、ということを延々と行っていた。
s51517765.hatenadiary.jp

f:id:s51517765:20171021223347j:plain

この本を読んでいたら、クリップボードのテキストを取得する方法が載っているのを見つけました。

もしかしたら、C#でもできるんじゃないか?と思い調べたら、もちろんできたので紹介します。

これを組み込めば、

Chromeで必要なPageを探す。
②①のURLをコピー
スクレイピングアプリをアクティブに
クリップボードの中身をペースト
⑤ボタンクリックで必要な情報ゲット!

という工程が、

Chromeで必要なPageを探す。
②①のURLをコピー
③ボタンクリックで必要な情報ゲット!

とすることができます。

ボタンクリックも省略することも可能ですが、必要なURLを取得しているかどうか確認する必要があるので、やりすぎは逆効果になることもあると思い今回は組み込みません。

ボタンクリックの時にクリップボードの中身を取得し、web取得を走らせることもできるが、ここでは、クリップボードにURLが取り込まれたらアプリにURLを入力するようにしました。
このためには定期的にクリップボードを確認し、URLが取り込まれたら、URL boxに取り込み、アプリをアクティブにする、というようにします。
(省略しますが、URLであるかどうかをクリップボードのテキストが"http"で始まるかどうかを確認することでURL以外では動作させないということもできます。)

これにはタイマーイベントを利用します。

Visual StudioのForm1.cs[デザイン]のツールボックスから、Timerコンポーネントを追加すします。
デザイン画面のフォーム外にタイマーコンポーネントが追加されるので、タイマーコンポーネントをダブルクリックします。
すると、タイマーイベント private void timer1_Tick() が作成されます。

f:id:s51517765:20171021225237j:plain

Form1_Loadでtimer1を起動し、Intervalをセットします。これが、クリップボードのチェック間隔になります。
Form1起動時に、クリップボードの中身を取得し、初期化。これを変数”clp_text0”としました。
timer1_Tick()がInterval毎に実行され、クリップボードの中身が変化していれば、textBoxURLに中身をテキストで入力されます。
bool check_clp というbool型変数を設定し、一度しか実行されないようにします。これをつけないと何度も起動されてしまいます。
異なるURLを連続して取得したいので、テキストの取得が完了したら、この変数は初期化します。

private void Form1_Load(object sender, EventArgs e)
    {
        InitializeComponent();
        string clp_text0;
        bool check_clp=false;
        timer1.Interval = 1000; //タイマーインターバル
        timer1.Start();
        clp_text0 = Clipboard.GetText(); //クリップボードの中身を取得、初期化
     }
       private void timer1_Tick(object sender, EventArgs e)
        {
            if (clp_text0 != Clipboard.GetText()&&check_clp==false)
            {
                textBoxURL.Text(Clipboard.GetText());
                check_clp = true;
                this.TopMost = !this.TopMost;  //フォームを最前面に
            }
        }

Pythonの  "if __name__ == ‘__main__’:" とモジュール化

pythonでよく使う処理を関数として作成し、他のプログラムから呼び出すことができます。

main.py

import a  #a.pyをモジュールとして読み込む
import b  #b.pyをモジュールとして読み込む

a.function()
print("a is done.")
b.function()
print("b is done.")

a.py

print("start a.")
def function():
  print("This is a.")
if __name__ == ‘__main__’:
  print("a is main.")
  function()

b.py

print("start b.")
def function():
  print("This is b.")
if __name__ == ‘__main__’:
  print("b is main.")
  function()

このように、3つのpythonプログラムを作成し、同じフォルダに格納します。
a.py を実行すれば、

start a.
a is main.
This is a.

という風に実行されます。b.pyも同様。

main.py を実行すると、main.pyが実行され、a.pyとb.pyが呼び出されます。

start a.
start b.
This is a.
a is done.
This is b.
a is done.

しかし、単独にa.pyとb.pyを実行したときと異なり、main.pyを実行したときは、"a is main."、"b is main."は実行されません。
これは、"if __name__ == '__main__':"の中にあるためです。
"if __name__ == '__main__':"は直接a.pyまたはb.pyを実行したときに実行されます。

qiita.com

一方、main.pyを見ると

a.function()
print("a is done.")
b.function()
print("b is done.")

a.function()、b.function()と直接、a.py、b.pyのfunction()を実行しているように見えますが、
実は、これらの前に記述されている

print("start a.")、 print("start b.")は実行されます。

実は、

import a  #a.pyをモジュールとして読み込む
import b  #b.pyをモジュールとして読み込む

#a.function()
print("a is done.")
#b.function()
print("b is done.")

とすると、

start a.
start b.
a is done.
b is done.

モジュールとして呼び込むと、その時点で、
if __name__ == ‘__main__’:
以外の部分が実行されるのです。

通常、pythonのプログラムを同時に複数実行することはできませんが、このようなことに気をつけさえすれば、main.py(親プロセスと呼ぶ)から呼び出すことで、2つ以上のプログラムを実行させることができます。
それぞれの起動条件はmain.pyの中でfunction()の起動条件として設定します。

Raspberry Pi 3を一からインストール

Raspberry Pi3を購入し、一からのインストールに挑戦しました。


f:id:s51517765:20171010215412j:plain

日経Linux 2017年 09 月号

日経Linux 2017年 09 月号

Windowsで実施しているこちらの記事を参考にしました。
qiita.com

公式サイトからNoobsをダウンロードします。
f:id:s51517765:20171009091241j:plain
ダウンロードは30分ぐらいかかります。
感覚的には、とても遅いです。
Zip圧縮ですが、7-zipというソフトを利用し解凍します。
このソフトも重要なようで、始め7-zipがうまく動作せず、「解凍レンジ」というものを使って解凍したのですが、うまくいきませんでした。
インストールは始まるものの、99%で止まって「パーティション」がどうこう~というErrorになってしまいました。

7-zipを実行するとエクスプローラのようなものが出てくるので、ここで、問題のzipを右クリックで解答します。
たぶんこれでOK。
f:id:s51517765:20171009112113j:plain

SD Cardはぐぐると動作確認されているものがいくつか出ているので、この中から選びました。

SD CardはSD Cdard Formatterを使用します。
ver.4で実施している記事しか見つからないのですが、Downloadは"ver.5"しかありません。
仕方なく5で試します。結果的には問題なかったようです。
クイックフォーマットで可です。
f:id:s51517765:20171009091244j:plain

zipの解凍とSD Cardのフォーマットができたら、zipの中身をSD Cardにドラックドロップでコピーし、ラズパイに差し込み電源を入れます。
前回のスターターキットの時と同じインストールするOSを選択する画面がでてきます。
ここからは前回と同じです。
もう、できたも同然。

インストールができたら、wi-fiを設定し、SSHを有効にしようとするが
前回のときのraspi-config\advanced OptionにSSHがない!
Raspberry PiをWindowsで操作する(SSH) | S2

Interfacing Optionsにありました。
qiita.com

こんなトラップが次々と出てくるんですね…。

Teratermを使い始めてから、使うことはないですが、念のためリモートデスクトップ接続もできるように、xrdpの再インストールもしておきます。
何かの時に役に立つかも。
ここまで、約3時間。前回と同じくらいかかりました。

s51517765.hatenadiary.jp
s51517765.hatenadiary.jp
s51517765.hatenadiary.jp

ラズパイから通知を送信 その2(LINE)

こちらを参考にしました。
qiita.com

こちらからアプリを登録します。
事前にスマホでLINEを登録してある必要があります。
登録されたアカウント(MAilアドレス)でLoginします。
notify-bot.line.me

マイページからアクセストークンを発行します。
f:id:s51517765:20171007232439j:plain

通知先を選びます。
自分のみに送信するだけであれば、1:1を選択します。
ここでは妻と共有するグループを選びました。
(グループ名は後で変更することもできますし、複数のアプリを登録することもできるようです。)
f:id:s51517765:20171007232448j:plain

スマホのLineアプリからLine Notifyをメンバーとして追加します。

グループの作成やメンバーの追加はこちらを参考にしました。
appllio.com
スマホでLineを受信したときにポップアップしない場合は、この辺を参考に、これでも通知が出ない場合は、Androidの設定から通知設定を確認してください。
dekiru.net

f:id:s51517765:20171008143127j:plain

TwitterのDirect Messageはリロードしないと読み込まなかったり、(アプリの設定によるかもしれませんが)アプリを起動していないときは通知に即時性がないので、LINEのほうが早いですね。とくにアンチLINEでなければLINEが使いやすそうです。

def send_line():
    url = "https://notify-api.line.me/api/notify"
    LINE_Token="*************"
    headers = {"Authorization": "Bearer " + LINE_Token}

    tdatetime = dt.now()
    message = 'Line_test_'+tdatetime.strftime('%H%M%S')
    payload = {"message": message}
    files = {"imageFile": open("A.jpg", "rb")}  
       #バイナリで画像ファイルを開きます。対応している形式はPNG/JPEGです。
    r = requests.post(url, headers=headers, params=payload, files=files) 
       #写真の添付が必要ないときは"files=files"を削除

ラズパイから通知を送信 その1(Twitter)

Raspberry Piで電子工作を進めているとラズパイから何らかの通知を送りたくなることがあります。
いつもコンソールを立ち上げている訳にはいかないので。

そこで、LANに標準で接続するラズパイだからこそ、ラズパイとpythonwebサービスを組み合わせてスマホに通知することをやってみます。

まずは、こちらのブログでも何度か取り上げていて私が最も力を入れているTwitterです。
TwitterにはDirect Messageがありますので、pythonでDirect Messageを送信し、スマホのTwiiterアプリやブラウザで受信します。

Direct Messageももちろんtweepyに盛り込まれていますので、公式Referenceをみて実装しました。
API Reference — tweepy 3.5.0 documentation

API.send_direct_message(user/screen_name/user_id, text)

こちらが、Direct messageのAPI classです。
()のなかがパラメータでスクリーン名もしくはユーザーID、ユーザー名と実際に送りたいMessage(text)であると推測できます。私はスクリーン名を使用しました。
スクリーン名とは@に続いて表示される、↓の例では "MomentsJapan" のようなもののことです。
ユーザーIDはint型の数字で表せれる固有の番号です。user classのデータを取得すると調べることができます。
userが "Twitter モーメント" のことでしょう(未確認なので使う場合は確認してね)
f:id:s51517765:20171007220108j:plain

# -*- coding: utf-8 -*-
import datetime
import tweepy

CONSUMER_KEY="****************"
CONSUMER_SECRET="****************"
ACCESS_TOKEN="****************"
ACCESS_SECRET="***************"
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
api = tweepy.API(auth)

def direct_messag():
    tdatetime = dt.now()
    api.send_direct_message(screen_name="宛先のスクリーン名",text="test "+tdatetime.strftime('%H%M%S'))

defで始まるものが、関数(メソッド)でapi.send_direct_messageで送信することができます。
ちなみに、Direct Messageは自分あてにも送信できるので、ラズパイから自身のアカウントへDMをを送信しスマホで確認することもできます。
text(DMの本文)はstring型なので、その中に含める内容はアイデア次第です。
f:id:s51517765:20171007221338j:plain

ちなみに、↑が私が現在ラズパイで運用しているTwitterアカウントです。
twitter.com

パソコンを修理(保証期間内)に出した話

AsusuのTransbook T102Hが立ち上がらなくなったので、修理した。

購入したのが今年の年初、製造が昨年2016年の10月と書かれている。
症状としては電源が入らなくなった。
結果的には1週間もかからず無償修理で戻ってきた。

戻ってきてからは充電の進み具合が爆速で、今まで使用しながら充電していてもインジケータがほとんど進まなかったし、充電ケーブルを抜いて放置していても一晩で起動しなくなるほど放電していたのだが、本来の性能はこれほどだったのかと驚いた。

9月20日(水)
夜に、PCを立ち上げようとするが”いつもの”充電切れで立ち上がらない。
いつもは15分ほど充電すればインジケータ5%ぐらいになって立ち上がるのだが、今日は1時間たっても2時間たっても立ち上がらない。あきらめて一日充電することに。

9月21日(木)
24時間充電しても立ち上がらない。
このとき電源ランプがオレンジ色に点滅している。いつもは充電中はオレンジ色の点灯なのに。
同じような症状がないかぐぐると、Transbookが立ち上がらない例がいくつか見つかる。
電源周りの故障と判断。
ASUS HPから問い合わせ。
S/Nなどを入れるようになっていてS/Nで自動的に機種名が表示される。
電源がオレンジの点滅で立ち上がらない、またデータのバックアップをとる方法があるかという質問もした。
(修理においては初期化して返却すると書いてあり、自己責任でバックアップしてから出すように、と書かれている。)

9月22日(金)
24時間弱で返信。
要旨は以下。

・ハードウェアのトラブルと考えられる。
・端末を修理センターに送っていただければ修理を進める。
・PCが起動しないのであればデータのバックアップをとる方法はない。
・修理後は初期化して返却するので、バックアップをとってから送付していただく。(ここで重大な矛盾が…)
・以上に同意いただければ、修理依頼の手順を案内する。

修理を依頼したいと返信。

ぐぐったときに、同じような症状で、電源ボタンを30秒ほど長押しすると立ち上がるという情報があったので試す。
30秒ほどで立ち上がろうとするが、電源ボタンを離すと落ちる。
そこで、セロテープで電源ボタンを押下状態で固定することでたちあげ、USBメモリにバックアップすることに成功。

9月23日(土)
S/Nで確認すると保証期間内であり、補償条件外(水こぼしなど)の要素がなければ無償で案内する。とのこと。
修理依頼書をLinkからダウンロードし、サポートあてに送付。

補償外の要素があったときは、見積もり後依頼するか、確認せずに進めるか、3万円以下なら確認せずに進めるか、の項目があり、3万円以下なら確認不要、で提出。

電源周りのときは電源アダプタ、usbケーブルも一緒に送るように、と書かれている。
usbケーブルは他のものと混ざりがちだが、急速充電に対応するものとしないものがあるので、電流の大きいものは純正品を使うように注意している。(純正品がなくなっていたらどうなっていたんだろう?)

9月24日(日)
届いたはず。

9月26日(火)
修理状況って見れるのかな?とおもって過去のMailを確認するとサポートページからS/Nを入力すると見れるらしい。
控えてないのであきらめる。

9月28日(木)
佐川急便で戻ってきた。

修理報告書がついていて、修理内容は
・当該症状が再現することを確認したので修理実施
・診断内容は、ハードウェア、OS、内部点検、外観点検、付属ケーブル点検、出荷前検証ツールテスト済み、とある。
具体的な修理内容は、
電源が入らないことを確認し、電源関連の再設定、とある。

液晶保護フィルムははがされて同梱されて戻ってきた。

Mailでのやり取りがすべてで、中国人か台湾人ポイひとが対応しているがMailのフォントが中国フォントだったり「てにおは」があいまいであったりするが、丁寧だし、某日本メーカーに以前プリンタの修理を出した時とは大違いだと思った。

Anacondaでpythonプログラミング & TeratermでRaspberry Piに転送

先日、Visual StudioPythonを導入したが、予測変換がいまいちだったり、反応が遅いのでAnaconda+Pycharmに変更しました。
まだ、debugのショートカットが"F?"ではありますが、vsでVC#を使っているときぐらいの使い勝手だと思ってます。

pythonIDEも数種類あるようですし、anacondaのようなパッケージもいろいろあると思いますが、私は↓で紹介されていることもありanacondaを使いました。

じつは、先日まで使っていたwin 10 PCが故障したので、いつもとはちがうwin7を使っています。
修理はできそうなので、これはこれで修理が終わったら、ここで報告しようと思う。

まずはインストールですが、ここを参考にすると、問題なくインストールできました。ちなみにWin7(pro 64bit)でも問題なくこれを参照してインストールできました。
www.procrasist.com

次にTwitterをつかうため、python用のライブラリ”tweepy”をインポートします。
Anacondaのプロンプトを立ち上げ、

$pip install tweepy

とします。
f:id:s51517765:20170924121255j:plain

最後に、デバックをしようとすると、インタプリタがないといってくるので、右上の歯車のところからインタプリタを設定します。
f:id:s51517765:20170928230845j:plain

これで、Windows上でAnaconda+Pycharmによるpython環境はできたことになります。

次にpythonのコードを作成したら、ラズパイに転送します。

まず、ラズパイにファイルを転送するためにTeratermを導入します。
↓を参照し、このとおりに進めれば問題ないです。
Raspberry PiをWindowsで操作する(SSH) | S2

ここで、標準インストールがおすすめ(適当にデフォルトのカスタムですすめたら接続できなかった)

あらかじめラズパイのIPは調べておきます。ポートは22に変更します。
ユーザー名とログインパスを入力すると、LT Tatminalが立ち上がり、LAN接続で操作できるようになります。
SSH(リモートデスクトップTeraterm接続)を始めると、パスワードを変更しろといってきます。セキュリティのためです。
そのままでも使えないことはないが

$sudo raspi-config

からパスワードを変更しておきましょう。

Teratermのターミナル画面に.py ファイルをドロップすると転送できます。
f:id:s51517765:20170924121815j:plain
すると、何かErrorらしいものがでました。

ラズパイにtweepyが入っていないためのようです。まずはtweepyをインストールします。

$sudo pip3 instal tweepy

ここでも"sudo" (管理者権限で実行を示す)を入れないとErrorになる。

$ls

で転送した.pyが表示されればOK。

$python3 twitter.py

で実行します。

検索してファイルに書き出す機能とテキストファイルからBot的に一定時間ごとにTweetする機能を作りました。

ちなみに、無限ループにしているので、停止は"Ctrl + c" です。

文字コードWindowsC#で使ったListを流用したかったので、"utf"を明示的に指定しています。
なんか、標準だとshift-jisかなにかで文字化けたので。

# -*- coding: utf-8 -*-
import random
import tweepy
import time
print("start_python!")

CONSUMER_KEY="**********"
CONSUMER_SECRET="**********"
ACCESS_TOKEN="**********"
ACCESS_SECRET="**********"
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
api = tweepy.API(auth)

def serch():  #関数定義
    keywords = [u'電子工作',u'秋葉原']
    query = 'OR'.join(keywords)
    file = open('serch.txt', 'a', encoding='utf')  # 追記モードでオープン
    for tweet in api.search(q=query, count=20):
        file.write(tweet.user.screen_name)
        file.write("\r\n")
        file.write()
        print("")
    file.close()

def Auto_tweet(): #関数定義
    rand=random.randint(1,109)
    n=0
    file=open('List.txt', 'r', encoding='utf') #UTFを指定する
    tweet="1"
    try:
        while tweet!="":
            tweet = file.readline()
            n=n+1
            if n == rand:
                break
        print(tweet)
        api.update_status(tweet)     #tweet
    except:
       Print("Tweet Error!")

while(True):
    serch()
    Auto_tweet()
    print("Sleep!")
    time.sleep(3600)