ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

apt-get updateに失敗

Raspberry Pi 3で、apt-get updateをすると、次のようなメッセージが表示されました。

インデックスファイルのダウンロードに失敗、アップデートが正常に出来なくなりました

ちょっと前まではできていたのに?
思いあたる節はIPアドレスを固定にしたことくらい。

/etc/dhcpcd.conf

interface wlan0
static ip_address=192.168.5.31/24
#static routers=192.168.5.254
#static domain_name_servers=125.173.93.22

固定IPアドレスにするだけだったのでルータとDNSサーバの指定はしなくてもいいと思っていたけど、もしかして固定IPアドレスにした場合はDNSサーバも指定しないとだめかもしれない?

/etc/dhcpcd.conf

interface wlan0
static ip_address=192.168.5.31/24
static routers=192.168.5.254
static domain_name_servers=125.173.93.22

ルータとDNSサーバを指定したところ、現象は直りました。
固定IPアドレスDHCP DNSの運用はどうすれば…。

systemdの'start request repeated to quickly, refusing to start'エラー

Raspberry Pi 3のRaspbian ver.8.0(Jessie)ではrc.localが非推奨となり、デフォルトで使用できなくなりました。
起動時にスクリプトを実行させたい場合、これからはsystemdを使いましょうとのことです。

systemdについての概要記事
http://equj65.net/tech/systemd-boot/

大体わかったような気がしたところで、とりあえず人のサンプルプログラムを動かしてみましょう。
http://qiita.com/DQNEO/items/0b5d0bc5d3cf407cb7ff
うまくいきました。

このサンプルプログラムを改造すればrc.localと同様の処理が実現できるというわけですね。少しずついじっていきましょう。少しずついじって…さっそくデーモンエラーが起きました。

$ systemctl -l status hello
● hello.service - hello daemon
   Loaded: loaded (/etc/systemd/system/hello.service; enabled)
   Active: failed (Result: start-limit) since 木 2017-01-26 14:58:38 JST; 2min 5
4s ago
 Main PID: 665 (code=exited, status=0/SUCCESS)

 1月 26 14:58:38 raspberrypi systemd[1]: hello.service holdoff time over, schedu
ling restart.
 1月 26 14:58:38 raspberrypi systemd[1]: Stopping hello daemon...
 1月 26 14:58:38 raspberrypi systemd[1]: Starting hello daemon...
 1月 26 14:58:38 raspberrypi systemd[1]: hello.service start request repeated to
o quickly, refusing to start.
 1月 26 14:58:38 raspberrypi systemd[1]: Failed to start hello daemon.
 1月 26 14:58:38 raspberrypi systemd[1]: Unit hello.service entered failed state
.

hello.service start request repeated too quickly, refusing to start.

「高速でリクエストを繰り返しすぎ」エラーのようです。

$ sudo vi /etc/systemd/system/hello.service
[Unit]
Descripton = hello daemon

[Service]
ExecStart = /opt/hello.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target

どうやら、Restart = alwaysが怪しいですね。
今、hello.shの中身は次のようになっています。

#!/bin/sh
echo Hello World >> /tmp/hello.log

このスクリプトが短すぎてすぐに処理が終わり、すぐにまたデーモンにリクエストがいっているせいでエラーが起きているようです。

Restart = noに書き換えてみましょう。

$ sudo vi /etc/systemd/system/hello.service
[Unit]
Descripton = hello daemon

[Service]
ExecStart = /opt/hello.sh
Restart = no
Type = simple

[Install]
WantedBy = multi-user.target

書き換えたら、hello.serviceを再度実行してみましょう。

$ sudo systemctl daemon-reload
$ sudo systemctl start hello
$ sudo systemctl status hello
● hello.service - hello daemon
   Loaded: loaded (/etc/systemd/system/hello.service; enabled)
   Active: inactive (dead) since 木 2017-01-26 15:44:25 JST; 2min 18s ago
  Process: 1006 ExecStart=/opt/hello.sh (code=exited, status=0/SUCCESS)
 Main PID: 1006 (code=exited, status=0/SUCCESS)

 1月 26 15:44:25 raspberrypi systemd[1]: Started hello daemon.

エラーが消えました。
hello.shを一回だけ実行したあと、inactiveになっています。
これでOKということで。

Raspberry Pi 3 の無線LANをWEPで接続

ルータに繋がらないなあと思っていたら、WPAじゃなくてWEPでした。大丈夫かなこの施設…

やり方はここのサイトの一番下に書いてありました。
https://www.freebsd.org/cgi/man.cgi?query=wpa_supplicant.conf&sektion=5&apropos=0&manpath=NetBSD+6.1.5

ラズパイが接続可能なアクセスポイントは、スキャンすることで見つかります

$ sudo iwlist wlan0 scan >> hoge.txt
$ less hoge.txt

ルータの情報は以下と仮定します。
SSID:MY_SSID
パスワード:HereIsPassword

Raspberry Pi 3のネットワーク情報はwpa_supplicant.confファイルを編集するらしいです。
(WEPで接続するのにwpa_supplicant.confを編集していいものか…まあいいや)

$ sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

country=JP
ctrl_interface=DIR/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
   ssid="MY_SSID"
   scan_ssid=1
   key_mgmt=NONE
   wep_tx_keyidx=0
   wep_key0=HereIsPassword
}

【2021/08/30追記】

Traditional WEP configuration with 104 bit key specified in hexadecimal.
Note the WEP key is not quoted.

wep_key0は、ダブルクオーテーションで囲まないことに注意してください。

【2021/08/30追記終わり】

scan_ssidとwep_tx_keyidxの意味はよくわかってないけれど、接続できました。

.gitignoreで、あるディレクトリの中身すべてを無視しない

次のようなディレクトリ構成があるとします。

├hoge2.txt
├hoge1.txt
├.gitignore
└main/
 ├ taskA/
 │ └ taskAA/
 │   └ taskaa.py
 └ test1.py
 └ test2.py

main/ディレクトリの中すべてのみをgitで管理したかったので、次のように書きました。

.gitignoreの中身

*         # すべて無視する
!/main/*  # ただしmain/ディレクトリ以下のファイルすべては除く

しかしこれではうまくいきませんでした。
この状態で git add . しても、なにもステージングされません。
この状態でステージングできるのは、main/ディレクトリのみです。しかし、gitは空のディレクトリのみは管理できないらしいので、実際は何もステージングされないということ(らしい)です。

main/ディレクトリ以下のファイルをステージングしたいならば、まずmain/ディレクトリ自体を除外する必要があります。

.gitignoreの中身

*         # すべて無視する
!/main/   # ただしmain/ディレクトリは除く
!/main/*  # ただしmain/ディレクトリ以下のファイルすべても除く

これでもまだダメです。
この状態でgit add .したら、次のファイルがステージングされます。

  • main/test1.py
  • main/test2.py

どうやら、ステージングされるのはmain/ディレクトリ直下のファイルのみのようです。
main/ディレクトリ直下のディレクトリも含めたすべてをステージングしたいならば、次のようにします。

.gitignoreの中身

*           # すべて無視する
!/main/     # ただしmain/ディレクトリは除く
!/main/**   # ただしmain/ディレクトリ以下のファイルもディレクトリすべても除く

これでOKです。
git add .すると、次のファイルがステージングされます。

  • main/test1.py
  • main/test2.py
  • main/taskA/taskAA/taskaa.py

難しいですね。

参考URL
http://qiita.com/anqooqie/items/110957797b3d5280c44f

ユーザコントロールから自身のWindowを取得する。それとLoadedイベント

Visual Studio 2010のWPFでアプリを開発中。
Windowにユーザコントロールを設置してあり、そのユーザコントロールのボタンが押された時にWindowのコントロール(ボタンとか)を制御したい。

ユーザコントロールから自身のWindowを取得するのは簡単。

(Window1) win = (Window1)Window.GetWindow(this);

ただ、このコードをユーザコントロールのコンストラクタに書いたらNullReferenseのエラーが発生する。
Loadedイベントとかに置いたらエラーは発生しない。
というわけでxamlにLoadedイベントを作ろう。

Control_MyControl1.xaml

<UserControl x:Class="MyProject1.Control_MyControl1"
                      xmlns="http://schemas.microsoft.com/womfx/2006/xaml/presentation"
                      (略)
                      Loaded="Control_MyControl1_Loaded" > <!-- Loadedを追加 -->

xaml.csにLoadedイベントハンドラを追加する

Control_MyControl1.xaml.cs

using System;
(略)
namespace MyProject1{
   public partial class Control_MyControl1: UserControl
   {
      (略)
      private void Control_MyControl1_Loaded(object sender, RoutedEventArgs e){
         (Window1) win = (Window1)Window.GetWindow(this);  
      }
   }
}

本当にLoadedイベントで良いのか?という疑問は残る。

似たような機能の関数を区別しやすいような関数名をつける

「左側のメニューにある複数のボタンのそれぞれについて、クリック可能/不可能を更新する」みたいな関数名をつけるとき、次の2種類を考えた。
・UpdateLeftSideMenuClickable
・UpdateClickableOfLeftSideMenu

どちらがよいか悩んだ時の方針として、とりあえず似たような機能の関数をつくってみる。

・UpdateLeftSideMenuClickable
・UpdateRightSideMenuClickable
・UpdateTopMenuClickable
・UpdateBottomMenuClickable

・UpdateClickableOfLeftSideMenu
・UpdateClickableOfRightSideMenu
・UpdateClickableOfTopMenu
・UpdateClickableOfBottomMenu

下側のほうが「UpdateClickableOf」まで共通なので、ぱっと見て区別がつくし、整理されている。
下のほうが良いよね、という話。

C# 16進数文字列を数値に変換する

数値を16進数文字列に変換するのはWEBを探せばよくあるが、その逆は見かけなかったので。

using System;
using System.Globalization;

public class Test
{
    public static void Main()
    {
    // your code goes here
    string str = "FF";
    int ans = int.Parse(str, NumberStyles.AllowHexSpecifier);

    Console.WriteLine("str:" + str);
    Console.WriteLine("ans:" + ans);
    }
}

↓結果

str:FF
ans:255

NumberStylesを使うためにはusing System.Globalizationが必要。