当初、NODE = ルータ(ゲートウェイ) と理解していましたが、次のような理解が正しそう
当初、NODE = ルータ(ゲートウェイ) と理解していましたが、次のような理解が正しそう
以下、何となく書いて、何となく、動いた程度。 何となくpythonで書いてみたけど、javaでも書くかな? (気が向いたら)
#!/usr/local/bin/python ## for python 2.7 # -*- coding: utf-8 -*- import asyncore import codecs import netifaces import socket import threading from time import sleep UDP_RESES = [] UDP_PORT = 3610 # for UDP def main(): # 自身のipアドレスを探索 local_ip = UdpSender.find_local_ip_addr() if local_ip == None: return None # echonetのコマンドをudp送信 sender = UdpSender(local_ip) # echonetのコマンド受信用thread recv = UdpReceiverThread() recv.start() echonet_cmd = echonet_cmd_ls() ##echonet機器の一覧取得用コマンド生成 # 224.0.23.0 とは、ECHONET専用のマルチキャストアドレス sender.send_msg("224.0.23.0", echonet_cmd) # 複数機器からレスポンスがある場合があるので、少々、待つ sleep(3) recv.stop() # UDP_RESES に各機器からのレスポンスが、echonet電文とIPで入ってます for udp_res in UDP_RESES: echonet_res = parse_echonet_res(udp_res[0]) print(udp_res) print(echonet_res) # 後はお好きに... def parse_echonet_res(echonet_res): res_cols = [echonet_res[ 0: 4], ## echonetであることの宣言 echonet_res[ 4: 8], ## 自由欄 echonet_res[ 8:14], ## SEOJ(送信元機器) 0ef001=ノード echonet_res[14:20], ## DEOJ(送信先機器) 05ff01=コントローラ echonet_res[20:22], ## 応答code. 71=set 72=get echonet_res[22:24], ## 処理プロパティ数 echonet_res[24:26], ## プロパティ名 d6=自ノードlist. echonet_res[26:28], ## PDC. 後のbyte数 echonet_res[28:36]] ## 0105ff01 = 1個(01)x05ff01 return res_cols ## http://qiita.com/miyazawa_shi/items/725bc5eb6590be72970d def echonet_cmd_ls(): cmd_cols = ["1081", ## echonetであることの宣言 "0000", ## 自由欄 "05ff01", ## SEOJ(送信元機器) 05ff01=コントローラ "0ef001", ## DEOJ(送信先機器) 0ef001=ノード "62", ## 60=set, 61=set(要:応答), 62=get "01", ## 処理プロパティ数 "d6", ## プロパティ名 d6=自ノードlist. ## https://echonet.jp/spec_v112_lite/ にある ## 第2部 ECHONET Lite 通信ミドルウェア仕様の ## 6.11.1 ノードプロファイル詳細規定 参照 "00"] echonet_cmd = "".join(cmd_cols) return echonet_cmd class UdpSender(): def __init__(self, local_ip): self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_ip)) def send_msg(self, ip,message): decode_hex = codecs.getdecoder("hex_codec") msg = decode_hex( message )[0] self.sock.sendto(msg, (ip, UDP_PORT)) def close(self): self.sock.close() @staticmethod def find_local_ip_addr(find_iface_name=None): for iface_name in netifaces.interfaces(): iface_data = netifaces.ifaddresses(iface_name) af_inet = iface_data.get(netifaces.AF_INET) if not af_inet: continue ip_addr = af_inet[0]["addr"] if find_iface_name == None: return ip_addr elif iface_name == find_iface_name: return ip_addr return None class UdpReceiverThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.server = UdpReceiver() def run(self): asyncore.loop() def stop(self): self.server.close() self.join() class UdpReceiver(asyncore.dispatcher): def __init__(self): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_DGRAM) self.bind(("0.0.0.0",UDP_PORT)) return def handle_read(self): data = self.recvfrom(4096) encode_hex = codecs.getencoder("hex_codec") global UDP_RESES UDP_RESES.append([encode_hex(str(data[0]))[0], data[1][0]]) return if __name__ == '__main__': main()
↑こう書くと、↓こう出力されます
C:\home\endo\tmp>\Python27\python.exe foo.py ['108100000ef00105ff017201d6040105ff05', '192.168.0.15'] ['1081', '0000', '0ef001', '05ff01', '72', '01', 'd6', '04', '0105ff05']
たまに、次のようなエラーが出力されますので、気が向いたら、調べます。
C:\home\endo\tmp>\Python27\python.exe foo.py Exception in thread Thread-1: Traceback (most recent call last): File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner self.run() File "foo.py", line 106, in run asyncore.loop() File "C:\Python27\lib\asyncore.py", line 216, in loop poll_fun(timeout, map) File "C:\Python27\lib\asyncore.py", line 145, in poll r, w, e = select.select(r, w, e, timeout) error: (10038, '\x83\\\x83P\x83b\x83g\x88\xc8\x8aO\x82\xcc\x82\xe0\x82\xcc\x82\xc9\x91\xce\x82\xb5\x82\xc4\x91\x80\x8d\xec\x82\xf0\x8e\xc0\x8ds\x82\xb5\x82\xe6\x82\xa4\x82\xc6\x82\xb5\x82\xdc\x82\xb5\x82\xbd\x81B')
国税庁が公開する 基本通達・法人税法 の 7-8-6の2 (ソフトウエアに係る資本的支出と修繕費)にある通り、 - 「ソフトウエアの機能の追加、向上」⇒(ならば) 資本的支出(≒資産計上)。 - バグ修正等、現状の維持該当 ⇒ 修繕費(≒経費処理OK) らしい。
https://www.nta.go.jp/shiraberu/zeiho-kaishaku/tsutatsu/kihon/hojin/07/07_08.htm
例えば、消費税法改正に伴うソフト修正は、経費処理がOKのよう。 https://www.nta.go.jp/shiraberu/zeiho-kaishaku/joho-zeikaishaku/hojin/0309/01.htm
html-tidy がいいのかな?
$ wget http://binaries.html-tidy.org/binaries/tidy-5.2.0/tidy-5.2.0-64bit.rpm $ su # rpm -ivh tidy-5.2.0-64bit.rpm $ tidy --help
ので
format() , int()が利用できるので…
#!/usr/local/bin/python # -*- coding: utf-8 -*- def main(): from_int() to_int() def from_int(): org_int = 10 for base in ["b","o","x","X"]: from_int = format(org_int,base) print base +":"+str(org_int) +"->"+ str(from_int) print '' def to_int(): for org_str, base in {"1010":2, "12":8, "a":16}.items(): print str(base)+":"+ org_str +"->"+ str( int(org_str, base) ) if __name__ == '__main__': main()
↑こう書くと↓こう実行できます
$ ./foo.py b:10->1010 o:10->12 x:10->a X:10->A 16:a->10 8:12->10 2:1010->10
Math::BaseCalc for perlのcloneを書く必要があるのかな? http://search.cpan.org/perldoc?Math%3A%3ABaseCalc
Math::BaseCalc かと思ったら、Excel::Writer::XLSX::Utility を使うようです。 http://search.cpan.org/perldoc?Excel%3A%3AWriter%3A%3AXLSX
#!/usr/local/bin/perl use strict; use warnings; use utf8; # use Math::BaseCalc; use Excel::Writer::XLSX::Utility; use Data::Dumper; main(); sub main { my $co_a1_org = "C2"; my ( $row, $col ) = xl_cell_to_rowcol( $co_a1_org ); print "$co_a1_org -> ($row, $col)\n"; my @co_r1c1_org = (2,30); my $co_a1 = xl_rowcol_to_cell( @co_r1c1_org ); print "($co_r1c1_org[0], $co_r1c1_org[1]) -> $co_a1\n"; }
↑こう書くと、↓こう変換できます
$ ./foo.pl C2 -> (1, 2) (2, 30) -> AE3
http://end0tknr.hateblo.jp/entry/20150819/1439950536 http://end0tknr.hateblo.jp/entry/20170205/1486293131
Email::Stuffer シリーズ?の第3弾?
メールソフト(MUA)に表示されるアドレスとは、別のアドレスにエラーメールを返送したい為、メモ。 まぁ、ググれば、分かるんですけどね
fromのtype | 説明(例) |
---|---|
envelope from | 封筒に書かれる差出人. 宛先不明時はこちらへ返送 |
header from | 便箋に書かれる差出人 |
宛先不明メールは、Return-Path宛に返送されます。 しかし、メールヘッダのReturn-Pathはメールサーバ経由時に書換えられる為、 単純にメールヘッダにReturn-Pathを設定しても意味がありません。
envelope fromこそが、メールサーガ経由時にReturn-Pathに設定される為、 envelope fromにエラーメールの返送先を設定する必要があります。
するには、次のように書きます。
ただし、試した範囲では、smtp.gmail.com での送信では、 好みのReturn-Path(envelop from)は設定できませんでした。
#!/usr/local/bin/perl use strict; use warnings; use utf8; use Email::Stuffer; use Email::Sender::Transport::SMTP; use Email::Sender::Transport::SMTP::TLS; use Data::Dumper; my $FROM = 'ないしょ@ないしょ.com'; ## HEADER FROM my $REPLY_TO = 'ひみつ@ないしょ.com'; ## ENVELOP FROM my $SUBJECT = 'TEST MAIL'; # auth smtpの場合 my $SMTP_CONF = {host => 'xxx.yyy.zzz.co.jp', port => 587, sasl_username => 'ないしょ', sasl_password => 'ないしょ', debug=>1}; # 素の場合 # my $SMTP_CONF = {host => 'ないしょ.co.jp', port => 25}; # auth smtp(tls)の場合 my $SMTP_TLS_CONF = {host => 'smtp.gmail.com', port => 587, username=>'ないしょ@gmail.com', password=>'ないしょ', # APPのパスワード debug=>1 }; main( @ARGV); sub main { my ($mailto) = @_; my $email = Email::Stuffer->new(); my $smtp = get_smtp_obj(); # my $smtp = get_smtp_obj_tls(); $email->transport( $smtp ); $email->subject($SUBJECT); $email->from($FROM); ## HEADER FROM $email->to($mailto); $email->header('Reply-To' => $REPLY_TO); my $txt_mime = get_txt_mime(); ## 代替text part my $html_mime = get_html_mime(); ## html part push(@{$email->{parts}}, $txt_mime); push(@{$email->{parts}}, $html_mime); $email->send_or_die({from=>$REPLY_TO}); ## ENVELOP FROM } sub get_smtp_obj_tls { my $smtp = Email::Sender::Transport::SMTP::TLS->new($SMTP_TLS_CONF); return $smtp; } sub get_smtp_obj { my $smtp = Email::Sender::Transport::SMTP->new($SMTP_CONF); return $smtp; } sub get_txt_mime { my $attr = {content_type => 'text/plain', charset => 'utf-8', encoding => 'quoted-printable', format => 'flowed'}; my $body =<<EOF; これは、テキストメールのテストです。 EOF my $mime = Email::MIME->create(attributes => $attr, body_str => $body); return $mime; } sub get_html_mime { my $attr = {content_type => 'text/html', charset => 'utf-8', encoding => 'quoted-printable'}; my $body =<<EOF; <html> <head></head> <body> これは、<b>HTML</b>メールのテストです。 </body> </html> EOF my $mime = Email::MIME->create(attributes => $attr, body_str => $body); return $mime; } 1;
Email::Stuffer や Email::Sender::Transport::SMTP 、 Email::Sender::Transport::SMTP::TLS に殆どおまかせなので、 以下のように書くだけでOK。
#!/usr/local/bin/perl use strict; use warnings; use utf8; use Email::Stuffer; use Email::Sender::Transport::SMTP; use Email::Sender::Transport::SMTP::TLS; use Data::Dumper; my $FROM = 'ないしょ@gmail.com'; my $SUBJECT = 'TEST MAIL'; # auth smtpの場合 my $SMTP_CONF = {host => 'ないしょ.co.jp', port => 587, sasl_username => 'ないしょ', sasl_password => 'ないしょ', debug=>1 }; # 素の場合 # my $SMTP_CONF = {host => 'ないしょ.co.jp', # port => 25}; # auth smtp(tls)の場合 my $SMTP_TLS_CONF = {host => 'smtp.gmail.com', port => 587, username=>'ないしょ', password=>'ないしょ', # APPのパスワード debug=>1 }; main( @ARGV); sub main { my ($mailto) = @_; my $email = Email::Stuffer->new(); # my $smtp = get_smtp_obj(); my $smtp = get_smtp_obj_tls(); $email->transport( $smtp ); $email->subject($SUBJECT); $email->from($FROM); $email->to($mailto); my $txt_mime = get_txt_mime(); ## 代替text part my $html_mime = get_html_mime(); ## html part push(@{$email->{parts}}, $txt_mime); push(@{$email->{parts}}, $html_mime); $email->send_or_die; } sub get_smtp_obj_tls { my $smtp = Email::Sender::Transport::SMTP::TLS->new($SMTP_TLS_CONF); return $smtp; } sub get_smtp_obj { my $smtp = Email::Sender::Transport::SMTP->new($SMTP_CONF); return $smtp; } sub get_txt_mime { my $attr = {content_type => 'text/plain', charset => 'utf-8', encoding => 'quoted-printable', format => 'flowed'}; my $body =<<EOF; これは、テキストメールのテストです。 EOF my $mime = Email::MIME->create(attributes => $attr, body_str => $body); return $mime; } sub get_html_mime { my $attr = {content_type => 'text/html', charset => 'utf-8', encoding => 'quoted-printable'}; my $body =<<EOF; <html> <head></head> <body> これは、<b>HTML</b>メールのテストです。 </body> </html> EOF my $mime = Email::MIME->create(attributes => $attr, body_str => $body); return $mime; } 1;
↓こんな感じで使用します。とうより、自分用メモ。
#!/usr/local/bin/perl use strict; use warnings; # http://tagomoris.hatenablog.com/entry/20120918/1347991165 use Getopt::Long qw(:config posix_default no_ignore_case gnu_compat); use Data::Dumper; my $cmd_opts = {}; main(); sub main { my $cmd_opts = {}; # Getopt::Long::GetOptions により引き数が蓄積 my @defined_opts = ('conf_file=s','mail_type=s','mail_data=s','subject=s','output=s'); #不明なoptionが与えられた場合 unless(Getopt::Long::GetOptions($cmd_opts,@defined_opts)){ print_usage(); return; } #本来?は、ここで、与えられた引き数をvalidataion if(scalar(keys %$cmd_opts)==0){ print_usage(); return; } #で、その後の処理に入る... } sub print_usage { print "Usage: $0 COMMAND [OPTION]\n"; print ' --conf_file=$FILE_PATH',"\n"; print " --mail_data=[NULL, BULK_MAIL]\n"; print ' --subject=$SUBJECT',"\n"; print ' --output=[NULL, FILE, $MAILTO]',"\n"; }
perlのsleepでは、1秒単位のsleepは組込み関数のsleep()、 1秒未満単位のsleepは Time::HiResの sleep() を使用しますが、 select(undef, undef, undef, $sleep_time)でも、Time::HiRes::sleep() と同様の動作をできるらしい。
#!/usr/local/bin/perl use strict; use warnings; use Time::HiRes; main(); sub main { for my $interval (1.5 , 1.0, 0.5){ my $start_time = Time::HiRes::time(); # http://perldoc.perl.org/functions/sleep.html sleep($interval); my $end_time = Time::HiRes::time(); my $slept_time = $end_time - $start_time; print "sleep( $interval )->slept time $slept_time sec\n"; } print "\n"; for my $interval (1.5 , 1.0, 0.5){ ## http://perldoc.perl.org/functions/select.html ## http://perldoc.jp/func/select my $start_time = Time::HiRes::time(); select(undef, undef, undef, $interval); ## = sleep my $end_time = Time::HiRes::time(); my $slept_time = $end_time - $start_time; print "select(undef,undef,undef,$interval)->slept time $slept_time sec\n"; } print "\n"; for my $interval (1.5 , 1.0, 0.5){ my $start_time = Time::HiRes::time(); ## http://search.cpan.org/perldoc?Time%3A%3AHiRes Time::HiRes::sleep($interval); my $end_time = Time::HiRes::time(); my $slept_time = $end_time - $start_time; print "Time::HiRes::sleep($interval)->slept time $slept_time sec\n"; } }
つまり↑こう書くと、↓こう表示されます
$ ./foo.pl sleep( 1.5 )->slept time 1.00030517578125 sec sleep( 1 )->slept time 1.00028395652771 sec sleep( 0.5 )->slept time 9.05990600585938e-06 sec select(undef,undef,undef,1.5)->slept time 1.50168013572693 sec select(undef,undef,undef,1)->slept time 1.00239300727844 sec select(undef,undef,undef,0.5)->slept time 0.500741958618164 sec Time::HiRes::sleep(1.5)->slept time 1.50391101837158 sec Time::HiRes::sleep(1)->slept time 1.00040507316589 sec Time::HiRes::sleep(0.5)->slept time 0.500246047973633 sec
らしく、↓このように怒られます
$ perlcritic foo.pl "select" used to emulate "sleep" at line 26, column 9. See page 168 of PBP. (Severity: 5)
http://search.cpan.org/perldoc?Math%3A%3ABigInt%3A%3ARandom ↓こうかな?
#!/usr/local/bin/perl use strict; use Math::BigInt; use Math::BigInt::Random; use Data::Dumper; main(); sub main { my $max = 18_446_744_073_709_551_615; my $i = 0; while( $i++ < 10 ){ print Math::BigInt::Random::random_bigint( max => $max ),"\n"; } }
$ ./test.pl 9506841540604143609 17290575413746988769 12642088427333715816 3437943406824129695 4510757347866451250 4637770013828130871 6569924293883749620 11166561186182411725 3618737948898655722 4641358188649576606
http://search.cpan.org/perldoc?Email%3A%3AStuffer
http://search.cpan.org/perldoc?Email%3A%3AMIME
Email::Stuffer & Email::MIME を読んでたら、Email::MIME では、encoding に base64 or quoted-printable or 8bit を指定できるらしい。
quoted-printable (いわゆる QP encoding)は利用したことがなかったので、お試し。
BASE64との違い等と合せて、ググった方が理解しやすいと思いますので、 ここでは記載しません。
perlで QP encoding するには、MIME::QuotedPrint を利用するよう。 しかも、標準module
http://perldoc.perl.org/MIME/QuotedPrint.html
$ corelist MIME::QuotedPrint Data for 2014-10-01 MIME::QuotedPrint was first released with perl v5.7.3 $ corelist MIME::Base64; Data for 2014-10-01 MIME::Base64 was first released with perl v5.7.3
#!/usr/local/bin/perl use strict; use warnings; use utf8; use Encode; use MIME::QuotedPrint; main(); sub main { for my $char_org ('1','A','+','=','あ','あA','あい','α','㈱'){ my $char_org_utf8 = Encode::encode('utf8',$char_org); my $encoded = MIME::QuotedPrint::encode_qp( $char_org_utf8 ); my $decoded = MIME::QuotedPrint::decode_qp($encoded); print join(" -> ", $char_org_utf8, $encoded, $decoded),"\n\n"; } }
↑こう書くと、↓こう表示されます。
$ ./test.pl 1 -> 1= -> 1 A -> A= -> A + -> += -> + = -> =3D= -> = あ -> =E3=81=82= -> あ あA -> =E3=81=82A= -> あA あい -> =E3=81=82=E3=81=84= -> あい α -> =CE=B1= -> α ㈱ -> =E3=88=B1= -> ㈱
「encode_qp()」された文字列の最後には、改行文字が追加されるみたい。
上記を参考に、以下のように書いてみた。
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <button type="button" onClick="log.error('LOG1','LOG2' );">TEST ERROR</button> <button type="button" onClick="log.warn('LOG1','LOG2' );">TEST WARN</button> <button type="button" onClick="log.info('LOG1','LOG2' );">TEST INFO</button> <button type="button" onClick="log.debug('LOG1','LOG2' );">TEST DEBUG</button> </body> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/Logger.js"></script> <script> $(document).ready(function(){ // log.set_level('none'); //必要であれば、出力ログレベルを設定 }); </script> </html>
(function() { var Logger = function(){ this.level = this.LEVEL['info']; // set default disp level }; Logger.prototype = { LEVEL : {none:0, error:1, warn:2, info:3, debug:4 }, SERVER_LOG_URL : '/client_log.png', //設定値があれば、サーバへログ送信 set_level: function(lavel){ this.level = this.LEVEL[lavel]; }, error : function(){ this._log(arguments.callee.name,this._args2array(arguments)); }, warn : function(){ this._log(arguments.callee.name,this._args2array(arguments)); }, info : function(){ this._log(arguments.callee.name,this._args2array(arguments)); }, debug : function(){ this._log(arguments.callee.name,this._args2array(arguments)); }, _is_disp: function( level ){ //console objや、log levelの確認 if(window.console && typeof window.console[level] === 'function' && this.level >= this.LEVEL[level] ){ return true; } return false; }, _log: function(func_name, msgs){ if(! this._is_disp(func_name)) return; console[func_name]( msgs.join(' ')); if(this.SERVER_LOG_URL ){ this._log_to_server(func_name, msgs); return; } }, _log_to_server: function(func_name, msgs){ //サーバへログ送信 var msgs_str = func_name +'='+ msgs.join('_'); var now = (new Date()).getTime() + Math.random() * 1000 ; var url = this.SERVER_LOG_URL +'?'+ encodeURI(msgs_str) +"&time="+now; var dummy_img = new Image(); dummy_img.src = url; }, _args2array : function(arguments){ //可変長引数対応の為、Array型に変換 var ret = []; for (var i = 0; i < arguments.length; i++) { ret.push(arguments[i]); } return ret; } }; window.log = new Logger(); })();
普通?にeclipseを起動し、メニューバー -> Help -> Installation Details で表示されるダイアログでも確認できますが、 windowsのコマンドプロンプトを起動し、equinoxコンソールでも次のように確認できます。
C:\>cd \eclipse C:\eclipse> eclipsec.exe -console : osgi>ss "Framework is launched." id State Bundle 0 ACTIVE org.eclipse.osgi_3.10.2.v20150203-1939 Fragments=1 1 RESOLVED org.eclipse.osgi.compatibility.state_1.0.1.v20140709-1414 Master=0 2 ACTIVE org.eclipse.equinox.simpleconfigurator_1.1.0.v20131217-1203 3 RESOLVED ch.qos.logback.classic_1.0.7.v20121108-1250 Fragments=533 4 RESOLVED ch.qos.logback.core_1.0.7.v20121108-1250 5 RESOLVED ch.qos.logback.slf4j_1.0.7.v20121108-1250 Master=836 6 RESOLVED com.google.guava_15.0.0.v201403281430 : : :
「bundle $no」と実行することで、指定したbundleの詳しい情報を表示できます(以下)
osgi> bundle 1 org.eclipse.osgi.compatibility.state_1.0.1.v20140709-1414 [1] Id=1, Status=RESOLVED Data Root=C:\eclipse\configuration\org.eclipse.osgi\1\data "No registered services." No services in use. No exported packages No imported packages Host bundles org.eclipse.osgi_3.10.2.v20150203-1939 [0]
主に利用するコマンドは以下で、その他はhelpをご覧下さい
osgi> start $bundle_id osgi> stop $bundle_id osgi> update $bundle_id osgi> refresh $bundle_id osgi> help
今回は以下を参考にしましたが、OSGIではIFと実装を別バンドルにするといいらしい。
FFI::Platypus - search.cpan.org
どうやら最近は、FFI::Platypus なるmoduleが存在し、 xs よりも簡単に c/c++ の関数を利用できるみたい。
SYNOPSIS のサンプルコードやdocumentを参照する限り、簡単そ