PeaceJetのブログ

金融系の社内エンジニアをやりながら、マーケティングやプランナーなども

Nature Remo 発売延期

楽しみに待っていたNatureRemoでしたが、機器の不具合が発覚したため発売を延期するとの連絡をいただきました。

nature.global

中途半端な製品を世に出せないという思い、共感いたします。

一旦、返金となるようですが、また発売日が決まったら申し込もうと思います。

【TensorFlow】TensorBoardでAttributeError

AttributeError: module 'tensorflow.python.training.training' has no attribute 'SummaryWriter'

上記のようなエラーが出た場合、'tensorflow.python.training.training'には 'SummaryWriter'属性は存在しません。
このように言われています。

ドキュメントを見てみると、2016年後半に機能がなくなっており、別のモジュールから呼び出さなければならないそうです。

import tensorflow as tf
sess = tf.Session()
tw = tf.train.SummaryWriter("log", graph=sess.graph)

上記を、下記のように変更してみましょう。
するとうまく行くはずです。

import tensorflow as tf
sess = tf.Session()
tw = tf.summary.FileWriter("log", graph=sess.graph)

【Raspberry Pi】Raspberry Pi 3 Model BでCaptivePortalする方法

Raspberry PiでCaptivePortal

仕事でWi-Fiに接続したら何らかのコンテンツを表示することができないか?と考えて、いろいろ調べてみるとキャプティブポータル(CaptivePortal)が使えるのではないかと考えました。

そこで、今回はRaspberry PiWi-Fi機能を利用して、DHCPサーバーからIPアドレスをもらうときにスプラッシュ画面が表示されるようにしてみたいと思います。

注意

知識不足のため、iPhoneで接続したときにCaptivePortal画面が出てきません。
ただ、パソコンでは画面が出てくることを確認しています。
誰か、解決策を知っている方がいらっしゃいましたら、コメントいただけるとうれしいです。

環境

  • Raspberry Pi 3 Model B & Rasbian Jessie With Pixelで構築しています。

アップデート

ファームウェアを更新します。
$ sudo rpi-update
再起動します。
$ sudo reboot
最新状態にアップデートします。
$ sudo apt-get update
$ sudo apt-get upgrade

IPアドレス

IPアドレスを固定します。

$ sudo nano /etc/network/interfaces
以下のように書き換えます。
auto lo
iface lo inet loopback

iface eth0 inet manual

allow-hotplug wlan0

iface wlan0 inet static
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

#allow-hotplug wlan1
#iface wlan1 inet manual
#    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
Raspbian Jessie では、/etc/dhcpcd.confの一番下に追記します。
$ sudo nano /etc/dhcpcd.conf
interface wlan0
static ip_address=10.0.0.1
static routers=192.168.1.1
static domain_name_servers=10.0.0.1

AP

hostapdをインストールします。
$ sudo apt-get install hostapd
hostapd.confファイルを作成します。
$ sudo nano /etc/hostapd/hostapd.conf
interface=wlan0
ssid=Free Wifi
country_code=JP
ieee80211d=1
hw_mode=g
channel=11
auth_algs=1
wmm_enabled=0
hostapd設定を変更します。
$ sudo nano /etc/default/hostapd
DAEMON_CONF="/etc/hostapd/hostapd.conf"
WPASupplicantを退避

WPASupplicantファイルが読み込まれないようにします。

$ sudo mv /usr/share/dbus-1/system-services/fi.epitest.hostap.WPASupplicant.service ~/

DNSMASQ

DNSDHCPサーバーを設置します。
$ sudo apt-get install dnsmasq
dnsmasqの設定を変更します。
$ sudo nano /etc/dnsmasq.conf
一番下に追記します。
log-facility=/var/log/dnsmasq.log
address=/#/10.0.0.1
interface=wlan0
dhcp-range=10.0.0.10,10.0.0.254,10m
no-resolv
log-queries
$ sudo update-rc.d dnsmasq defaults

iptables

$ sudo nano /etc/iptables/rules.v4
$ sudo iptables -A INPUT -i wlan0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
$ sudo iptables -A INPUT -i wlan0 -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -i wlan0 -p udp --dport 53 -j ACCEPT
$ sudo iptables -A INPUT -i wlan0 -p udp --dport 67:68 -j ACCEPT
$ sudo iptables -A INPUT -i wlan0 -j DROP
$ sudo iptables-restore < /etc/iptables/rules.v4
iptablesにルールが追加されているかを確認します。
$ sudo iptables --list

Nginxのインストー

$ mkdir nginx-1.8.0
$ cd nginx-1.8.0
$ wget http://nginx.org/download/nginx-1.8.0.tar.gz
$ tar -zxvf nginx-1.8.0.tar.gz
$ cd nginx-1.8.0
$ sudo apt-get install curl build-essential libpcre3-dev libpcre++-dev zlib1g-dev libcurl4-openssl-dev libssl-dev
$ ./configure
$ make
$ sudo make install
$ sudo apt-get install php5-fpm
$ cd ~
$ sudo nano /usr/local/nginx/conf/nginx.conf

以下のように書き換えます。

#user nobody;
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    root /usr/local/nginx/html;
    index index.php index.html index.htm;

    server {

        listen 80;
        server_name localhost;

        error_page 404 http://10.0.0.1/index.html;

        location http://captive.apple.com/hotspot-detect.html {
               rewrite ^(.*)$ http://10.0.0.1/index.html last;
        }

        if ( $http_user_agent ~* (CaptiveNetworkSupport) ) { 
            return 302 http://10.0.0.1/index.html; 
        }

        location ~ \.php$ {
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;
        }

    }
}

PHPパーミッションを変更します。

$ sudo nano /etc/php5/fpm/pool.d/www.conf
listen.owner = www-data
listen.group = www-data
listen.mode = 0666

自動起動設定

$ sudo nano /etc/rc.local

exit 0手前に追記

$ sudo /usr/local/nginx/sbin/nginx

OSの調整
syslogにavahiのwarning出てるのでサービス停止

$ sudo service avahi-daemon stop
$ sudo update-rc.d -f avahi-daemon remove
kernel lacks cgroups or memory controller not avaiable, not starting cgroups [warn]
$ sudo nano /boot/cmdline.txt

変更箇所

rootfstype=ext4 elevator=deadline <span style="color:red">cgroup_enable=memory</span> rootwait

動作の確認
電源OFF

$ sudo shutdown -h now

パソコンで接続した場合には、自動的にブラウザが表示されてNginxのウェルカムページが表示されるはずです。

iPhoneではならず・・・。

おそらく、CaptivePortalチェックした場合にSuccessが返ってきてしまっているのではないかと考えています。
Nginx上で制御しているので、このあたりをもっと改善できればといろいろいじったのですが・・・。
結果は変わらず・・・。


DHCPサーバーからIPアドレスが得られているのがわかります。

※ 以下の記事を参考にさせていただきました。
野良Wi-Fiでコンテンツ配信2 - ディーズガレージ wiki
Raspberry Pi 2 (Raspbian: jessie) でIPアドレスを固定する - Qiita
Ubuntuでiptablesの設定をiptables-persistentで永続化する
Raspbian(jessie)の固定IPアドレス設定方法

【VBA】Excelマクロを使って年代を調べよう!【連想配列】

Excelマクロを使って年代を調べよう!

久しぶりに、VBAを書くような気がします。
会社勤めをしている人は、分かって頂けると思いますが。
どうしてもExcelが身近なツールとなり、仕事を下支えする存在になっています。

最近では、MarketoとかSalesforce、kintoneとか巷で話題の最新のツールを使う機会があれども、
ローカルでの管理はExcelに頼っているという実情もあるかと思います。

ローカルとリモート。
パソコンの知識とITリテラシー

埋まらない社内SEと運用者のミゾ・・・。

f:id:PeaceJet:20170712102026p:plain

上記のように、A列に年齢データがあるとします。
簡単に、年代と人数を調べたいなと思って、以下のコードを書きました。

10代~90代までを連想配列に入れる方法で、動作します。

※注意※ 「ツール」→「参照設定」→「Microsoft Scripting Runtime」を有効にして下さい。

外部のライブラリを使用しないように、Collectionとかを使って実装してみたのですが。
Keyが上手く取れなかったので、結局、Scripting RuntimeからDictionaryを使うことにしました。

途中で、すごい勢いで初期化しておりますが、これをしないと結果が空欄になってしまうので仕方ないかと。

Public Sub SearchAge()

    Dim aWs As Worksheet: Set aWs = ThisWorkbook.ActiveSheet
    Dim Tenth, Twentyth, Thirtyth, Fourtyth, Fiftyth, Sixtyth, Seventyth, Eightyth, Ninetyth As Long

    Dim Age As Object: Set Age = New Scripting.Dictionary
    
    Tenth = 0
    Twentyth = 0
    Thirtyth = 0
    Fourtyth = 0
    Fiftyth = 0
    Sixtyth = 0
    Seventyth = 0
    Eightyth = 0
    Ninetyth = 0
    
    For i = 2 To aWs.Range("A65535").End(xlUp).Row
        
        Select Case aWs.Range("A" & i).Value
            
            Case 10 To 19
                Tenth = Tenth + 1
            Case 20 To 29
                Twentyth = Twentyth + 1
            Case 30 To 39
                Thirtyth = Thirtyth + 1
            Case 40 To 49
                Fourtyth = Fourtyth + 1
            Case 50 To 59
                Fiftyth = Fiftyth + 1
            Case 60 To 69
                Sixtyth = Sixtyth + 1
            Case 70 To 79
                Seventyth = Seventyth + 1
            Case 80 To 89
                Eightyth = Eightyth + 1
            Case 90 To 99
                Ninetyth = Ninetyth + 1

        End Select
    
    Next i
    
        Age.Add Key:="10代", Item:=Tenth
        Age.Add Key:="20代", Item:=Twentyth
        Age.Add Key:="30代", Item:=Thirtyth
        Age.Add Key:="40代", Item:=Fourtyth
        Age.Add Key:="50代", Item:=Fiftyth
        Age.Add Key:="60代", Item:=Sixtyth
        Age.Add Key:="70代", Item:=Seventyth
        Age.Add Key:="80代", Item:=Eightyth
        Age.Add Key:="90代", Item:=Ninetyth
        
    Dim Key As Variant: Key = Age.Keys
    
    aWs.Range("B" & 1) = "年代"
    aWs.Range("C" & 1) = "人数"
    
    For k = 1 To 9
    
         aWs.Range("B" & k + 1) = Key(k - 1)
         aWs.Range("C" & k + 1) = Age(k & "0代")
    
    Next k
    
'        Debug.Print Age("10代")
'        Debug.Print Age("20代")
'        Debug.Print Age("30代")
'        Debug.Print Age("40代")
'        Debug.Print Age("50代")
'        Debug.Print Age("60代")
'        Debug.Print Age("70代")
'        Debug.Print Age("80代")
'        Debug.Print Age("90代")

End Sub

Amazonプライムデーに犬っころが出品される

今日から、Amazonプライムデーらしいですね。

何を買おうかなぁ~何かあるかなぁ~などと思いホームページを見てみたら犬が出品されていました。

どうやったら、購入ボタンまで到達できますか?

f:id:PeaceJet:20170710192824p:plain

Windows Subsystem for LinuxをPuttyで使うためのTips

Windows Subsystem for LinuxPuttyで使う

どうも、cmdやPowerShellだと慣れないしフォントも自由にならないので、SSHサーバーをローカルに立ち上げて、Puttyで接続して使ってみたいと思います。

① あらかじめインストールされていたsshサーバーを削除します。
$ sudo apt-get remove openssh-server
② 再度、インストールします。
$ sudo apt-get install openssh-server
sshd_configを開きます
$ sudo nano /etc/ssh/sshd_config
④ rootログインを拒否します
PermitRootLogin no
⑤ その下に次のような行を追加します。
# usernameをログインユーザーに置き換えます。
AllowUsers username
# AllowUsers Piなど
⑥ パスワードを使用してログインを有効にする
PasswordAuthentication yes
⑦ 追加/変更による権限分離を無効にする
UsePrivilegeSeparation no

設定が完了したので、Ctrl + o で上書き確認画面を出し、Enterします。そして、Ctrl + xで nanoを閉じます。

sshを再起動します。

restartだけだと、うまく動作しません。

sudo service ssh --full-restart
PuTTYを起動します。

localhost/22で接続してみてください。
WindowsからLinuxサブシステムに接続できるようになります。

【訂正】
正式には、Bash on Ubuntu on WindowsではなくてWindows Subsystem for Linuxらしいですね・・・。
どっちでもええわ!という感じなのですが、一応、正式な表記に修正しました。

【Raspberry Pi】 /etc/rc.localが実行されない問題について

Raspberry Piで/etc/rc.localが実行されない

f:id:PeaceJet:20170708001348p:plain

Linux起動時に、プログラムを実行してくれるrc.localですが、
なぜか自分の環境では動作しませんでした。

これまで、フォルダのパーミッションを変更したりとかやってみましたが。

結果的には、コンフィグ画面からBoot環境を変更することで解決することがわかりました。

① 以下のコマンドをターミナルへ入力します。
sudo raspi-config
② コンフィグ画面から「Boot Options」を選択します。

f:id:PeaceJet:20170707235636p:plain

③ 「B2 Wait for Network at boot」を選択します。

f:id:PeaceJet:20170707235659p:plain

④ <はい>を選択します。

f:id:PeaceJet:20170708000616p:plain

⑤ <了解>を選択します。

f:id:PeaceJet:20170708001018p:plain

⑥ 再起動します。
sudo reboot

これで、試してみてください。
おそらくrc.localに書かれたプログラムが動作すると思います。