2022年9月25日日曜日

数年前作成したグループウエアをGCEでためしてみた。

 古いシステムを動かしてみた。けっこう大変だった。

・JavaのバージョンをJava8にしないとだめだった。Tomcat9は使えたが。

・Mysqlの仕様変更があり、SSH上では、rootが作成できず、適当なユーザー名を作って、それに権限を与えることでなんとか動かせた。

やはり、一筋縄ではいなかようだが、時間かければなんとかなるということ。

gce インスタンスでTeraterm使えず

鍵生成をいろいろな方法で試してみたり(ユーザー名、鍵の形式、GCEの権限内容等々) 

いろいろ試行錯誤してだめだった。困っていたところ、

こちらの情報によると、インスタンス内のOSがSSHに厳しくなっているのが原因らしい。サイトの情報をもとに設定したら、使えるようになった。

2022年9月24日土曜日

GCEでWinSCPを使う

 GCEのインスタンスにファイルを転送するためWinSCPを使えるようにしてみた。秘密鍵、公開鍵の扱いに不慣れなので、いろいろ勉強になった。

はまったところ:
・秘密鍵を作成したときに、ローカルPCでのユーザー名がファイルの中に情報として入ってしまうようで、WinSCPでリモートにアクセスする際のユーザー名は、リモートのユーザー名ではなく、あくまでローカルPCでのユーザー名にしないとだめだった。基本的なことのようだが、今まで知らないでいた。
・WinPCは、直接秘密鍵が利用できず、.ppkなる拡張子のファイルに変換する必要があった。
・ポートは、セキュリティ上のこともあり外部からのアクセスでは標準の22を使わないことにした。インスタンスの中のsshサーバの設定には、
 port 22
 port 任意のポート番号(/etc/ssh/sshd_config)
のように2つ並べて置き、リモートからは22以外のほうを使うことにした。ルータとインスタンスのファイアーウオールの設定もそれにあわせて追加する必要がある。

いろいろなサイトを参考にさせていただいた。

・Dos Promptからもsshコマンドを使って手軽に確認もできるようだ。(秘密鍵生成などもできたり)
 ssh サーバアドレス(ホスト.ドメイン名もok) -i 秘密鍵ファイル名 -p 任意のポート番号

いろいろと手間はかかるようです。

2022年9月23日金曜日

GCEのインスタンスをつくってみた

 Herokuクラウドの無料枠もなくなったので、まだ無料枠が残っているGCEを使ってみた。

インスタンスの使い方がわからず、とまどったが、ネット上の情報に助けられる。まず、プロジェクトを作成する必要がある。ここで、適当に北米など選んでしまい、あとで、東京もあることに気づき、やり直すことに。ドメインは、すでに持っていたものを使い、DNSの設定なども必要に、TXT,Aレコードなどを追加していった。これに、今後はさらに、SSL化のために、証明書の発行なども必要になってきたり、Tomcatを使う予定なので、ポートの変換など、いろいろ手間がかかりそうだ。

 プロジェクトのあとは、インスタンスを作成、これがDockerのような仮想サーバなのだろう。OSや、CPUも選べるし、柔軟なカスタマイズができそう。そのぶん、設定項目が多くなってしまうが。

 つぎに、ターミナルがブラウザで表示なるので、てっきりここで、インスタンスの中を覗けるものだとだと勘違いしていた。何度か、SSHやApacheの設定を挑戦しても、外からアクセスできなかったので、おかしいなと、ルータのパケットフィルターやら、サーバのファイアーウオールやら、Apacheのポート変更やら、試行錯誤繰り返した。それでもうまくいかない。

 それもそのはず、インスタンスは、すぐ下のターミナルで操作するのでなく、「SSL」という小さなボタンをクリックすることで、それぞれのインスタンスの中をSSLで覗くことになるのだった。これに気づくまで、だいぶ時間がかかってしまう。ようやく、外からHTTPにアクセスできるようになる。

2022年9月22日木曜日

タッチセンサー+Arduino Uno+Dfplayer  シリアル通信で動かしみた


タッチセンサ 音楽プレーヤを作ってみました。

使い方:
①Mp3ファイルの準備
01~05のフォルダにそれぞれ、001.mp3~003.mp3の曲を入れておく
98のフォルダには、001.mp3に「音を小さくしました」、002.mp3に「音を大きくしました」という音声をいれておく。
99のフォルダには、001.mp3に「1番目のフォルダに切り替えました」のような音声を入れておく。これを5番まで作成。
②ボタンを押すと、フォルダが切り替わる。タッチセンサ3つに、3曲割り当てられる。
タッチセンサを押さないと、フォルダ切り替えはできないようにしてある。
③ボタンを押しながら、左側のタッチセンサに触ると、音量を下げられる。右側のタッチセンサに触ると、音量を上げられる。

arduinoのスケッチ

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
//void printDetail(uint8_t type, int value);
  const int SENSOR4 = 4;
  const int SENSOR5 = 5;
  const int SENSOR6 = 6;
  const int DIN_PIN = 7;
  int foldernumber=1;
  bool cflg=false;
void setup()
{  
  pinMode( DIN_PIN, INPUT_PULLUP );
  pinMode(SENSOR4, INPUT);
    pinMode(SENSOR5, INPUT);
      pinMode(SENSOR6, INPUT);
  delay(1000);
  mySoftwareSerial.begin(9600);
   if (!myDFPlayer.begin(mySoftwareSerial)) { 
    while(true);
 }
  myDFPlayer.setTimeOut(500); 
  myDFPlayer.volume(15); 
  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
   myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
}

void loop()
{
  if (digitalRead(SENSOR4)==HIGH) {
   myDFPlayer.playFolder(foldernumber,1 );  
    cflg=false;
  } 
  if (digitalRead(SENSOR5)==HIGH) {
   myDFPlayer.playFolder(foldernumber,2 );  
    cflg=false;
  } 
  if (digitalRead(SENSOR6)==HIGH) {
   myDFPlayer.playFolder(foldernumber,3 );  
    cflg=false;
  } 
   delay(1);

  if(digitalRead(DIN_PIN)==LOW ){
   if (digitalRead(SENSOR4)==HIGH) {  
      myDFPlayer.volumeUp(); 
      myDFPlayer.playFolder(98,2 );  //ageru saisei
      cflg=false;
   }else if(digitalRead(SENSOR6)==HIGH){
      myDFPlayer.volumeDown(); //Volume down
      myDFPlayer.playFolder(98,1 );  //sageru saisei 
      cflg=false;
   }else if(!cflg){        
     foldernumber=rand() % 5 + 1;
     myDFPlayer.playFolder(99,foldernumber ); //foldernumber onsei saisei
     cflg=true;
   }
  }

}

2022年9月21日水曜日

Dfplayerをarudunoのserial通信で制御

 Arduino Unoだと、上手く制御できそうなことは、わかったが、実際の組み上げにはいくつか、注意が必要だった。IOTの慣例?みたいなものがあるかも。知っている人にとってはどうということないことなのかもしれないが。

・電源は、Unoを経由せず、5v電源に繋がないと、安定しなかった。

・USB経由のserial通信は、pcと繋がないなら不要なので、コードから削除した。

・Delay関数で、dfplayerとの、通信は、立ち上げ後、1secしてから、開始させてみた。

・Net上のライブラリを使ったが、フォルダとmp3ファイルどちらも、0を先頭につけ桁数を揃える必要がある。(フォルダ、ファイル指定して再生する場合)

シリアルだと、2つのボタン押しに機能を持たせたり、カスタマイズの幅が広がり、なかなかいい。

Win11で慣れるまで少し時間がかかったこと

 Win11になり、よく使うメニューが変更になりとまどう。
 ファイル名の変更がわからず、「その他のオプション表示」から探していたが、よく考えたら、けっこう使用頻度が高いはずなんだけど面倒だなと不思議に思っていた。調べてみたら、コピペ同様、小さなアイコンで操作するといいということがわかった。他にも、F2キーを使う等の方法もあるようだ。
 ほかに、慣れる必要あるものとして
・コントロールパネルの出し方は、スタートボタンから検索Boxにconなどと入力すると出てくる。このへんは、Linuxっぽくなってきた感じがする。
・スタートボタンは、左クリックのメニューもよく使う。コンピュータの管理、ディスクの管理。結局、Winxpや7のときから使っていたようなものの場所が、win10,win11と変わるたびに変更されていくので、そのたびに、メニューをさがすのに時間がかかるようになってしまい、非効率。なんらかの法則的なものがあるとか、メニューの新たな探し方を追加で入れてもらうにはいいのだけど、変更は、やはりきつい。できれば、あまり変えないでほしいというのが、素直な感想。
・Linuxなども、ネットワークの設定コマンドがバージョンにより変わってきたりもするが、基本的なCUIコマンドが変わることはほとんどない。CUIも覚えるのは大変だが、いったん覚えれば、いつまでも使えるので、WinとLinuxそれぞれ一長一短があるといったところか。

 技術というのは、できれば、古い形式にも対応できるようにしながら、新しいものを追加していければ理想なのだろうけど。
 地デジへの移行の際も、いきなり古いアナログTVは使えませんではなくて、古いTVでも対応できる新しい電波形式にするとか(アナログからデジタルに一気に変更でなく、アナログにデジタルを追加したようなものを考えるとか)してもらえば、利用者に優しいものになったのだろうけど。。。
 たしか、FM放送は最初モノラル電波で、途中からステレオ電波になったはずです。そのとき、古いモノラルのラジオでも、ステレオの電波をモノラルで受信できるような形式に工夫されていたはず。。


2022年9月20日火曜日

gession 回覧の返信可能に

 以前から思っていたのですが、グループセッションの回覧機能に返信機能があるといいなと考え、Jqueryなど使い実装してみた。けっこう時間はかかったが、なんとか完成した。コンパイルせず、JSPだけでなんとかできた。

 ただし、ユーザーIDの扱い方がよくわからず、全角の氏名を使ってデータを扱うことにした。簡易的な方法なので、同じ職場にまったく同じ漢字の氏名の人がいると使えません。なんらかの形で文字を微妙に調整するとかする必要があります。

 でも、よく考えたら、同一漢字のままでグループウエアを運用することはないでしょう、おそらく運用上は部署名をつけるとかすると思うので、あまり関係ないかもしれませんが。


cir020.jsp
以下抜粋です。HTMLタグに必要なID属性なども追加必要です
<!-- 追加2022.9.19 -->
  <html:form styleId="cir010Form" action="/circular/cir010">
    <input type="hidden" name="CMD" value="search">
    <input type="hidden" name="reply_name" id="reply_name" value="">
    <input type="hidden" name="reply_title" id="reply_title" value="">
    <input type="hidden" name="reply_naiyo" id="reply_naiyo" value="">
  </html:form>

<!-- 追加2022.9.19 -->
<script>
$(document).ready( function(){
     setTimeout(function(){ 
          document.getElementById( "reply_name" ).value=document.getElementById( "hassin_name" ).textContent; 
           document.getElementById( "reply_title" ).value=document.getElementById( "reply_title_src" ).textContent;
           document.getElementById( "reply_naiyo" ).value=document.getElementById( "reply_naiyo_src" ).textContent;   
     },100);
    });
</script>
cir040.jsp
<%
String reply_title = "RE:"+request.getParameter("reply_title");
String reply_naiyo = "\n*********************Original Message*****************"+request.getParameter("reply_naiyo");
%>
<span id="reply_name2">
<%=request.getParameter("reply_name")%>
</span>


<!-- 追加2022.9.20 -->
<script>
$(document).ready( function(){
 
    setTimeout(function(){     
        var functinBtnName = $(".cir_send_sel_btn").attr('id');
        var paramStr = "CMD=getInitData";
        paramStr += getNowSelUsr();
        getSelAtesakiData(paramStr, functinBtnName, 0);             
    },100);    
        
    setTimeout(function(){     
        /* テンプレートポップアップ */
        $('#atesakiSelPop').dialog({
            autoOpen: false,  // hide dialog
            bgiframe: false,   // for IE6
            resizable: false,
            height: 0,
            width: 0,
            modal: true,
            overlay: {
              backgroundColor: '#000000',
              opacity: 0.0
            },
            buttons: {
              閉じる: function() {
                  $(this).dialog('close');
              }
            }
        });       
    },100);


    setTimeout(function(){     
      const list = document.getElementById('cmn120SelectLeftUser')
       const options = list.options
       Array.from(options).forEach(function(option) {
            if (option.label.trim() == $('#reply_name2').text().trim() ){
          option.selected=true         
           }

      }); 
       },300);
    
    setTimeout(function(){    
       var paramStr = "CMD=addUserData&";
           paramStr += getFormData($('#atesakiSelForm'));
           getSelAtesakiData(paramStr, $('#funcBtnName').val(), $('#funcBtnKbn').val());    
       },400);
    
    setTimeout(function(){     
    drawPopUsr();
    },500);
     
   });
</script>





2022年9月17日土曜日

Django 覚書14 WARNINGS: ?: (urls.W005) URL namespace 'admin' isn't unique. You may not be able to reverse all URLs in this namespace

 https://stackoverflow.com/questions/47933278/django-project-namespace-admin-isnt-unique を参考にさせていただきました。

path('admin/', admin.site.urls)を重複して、urls.pyに指定していたのが原因だった。Top階層のurls.pyのみに指定すると、解決。

2022年9月15日木曜日

Sqlite dump backup restore & 初期化

SQLiteのバックアップと復元は、こんな感じでできる。
backup
sqlite3 db.sqlite3
sqlite> .databases
sqlite> .output /dirname/test.dump
sqlite> .dump table_name
restore
% rm db.sqlite3
% sqlite3 test.dump < test.dump
****************
初期化したいときは、各アプリのmigrationsフォルダとdb.sqlite3をするといいという説明のサイトがあったので、実際やってみたが、うまくいかない。
別のサイトの情報では、migrationsフォルダの中の_init_pyは残して、他は削除とあった。この方法だとうまくいった。と、思ったら、エラーメッセージが出て、0001_initial.pyが必要という指示が出る場面があった、指示通りバックアップからファイルを追加したら、解決したというものもあった。微妙に調整が必要な場合もある?ようだ。そういうことに備えて、migrationsも、バックアップとってから削除したほうがいいかもしれない。

2022年9月11日日曜日

Django 覚書13 スクエアをsandboxからproductionに切り替えるにあたって

※View内のenviroment切り替えは、environment=request.site.sitedetail.production_sandbox

のような形で、adminのサイトページにSelectコントロールを追加し、sandboxとproductionの切り替えをすぐできるようにした。

ネット上のマニュアルを翻訳してみた。***********

Follow the steps to open the Developer Dashboard, but this time choose Production mode and copy the production application ID and access token.手順に従って開発者ダッシュボードを開きますが、今回は本番モードを選択し、本番アプリケーション ID とアクセス トークンをコピーします。

Update the domain string in the JavaScript reference from sandbox.web.squarecdn.com/v1/square.js to web.squarecdn.com/v1/square.js.JavaScript リファレンスのドメイン文字列を sandbox.web.squarecdn.com/v1/square.jsからweb.squarecdn.com/v1/square.js に更新します

The Web Payments SDK requires a valid application ID to return a payment token. Update the code by providing your production application ID.Web Payments SDK では、支払いトークンを返すために有効なアプリケーション ID が必要です。本番アプリケーション ID を指定してコードを更新します。

 In the "Configure the backend with your access token" section, you provided a Sandbox access token. Replace it with the production access token.「アクセス トークンを使用してバックエンドを構成する」セクションで、サンドボックス アクセス トークンを指定しました。これを本番アクセス トークンに置き換えます。

If you want to test the application in a production environment (squareup.com), you must use an actual payment card. Note that Square actually charges payment cards in production. Therefore, if you must test in production, charge minimum amounts.本番環境でアプリケーションをテストする場合 ( squareup.com)、実際の支払いカードを使用する必要があります。Square は実際に本番環境で支払いカードに課金することに注意してください。したがって、本番環境でテストする必要がある場合は、最小限の料金を請求してください。


Django 覚書12 Pythonのmap filter等の使い方で注意が必要なこと

 スクエアのサブスクリプションのリストには、カスタマーIDが表示されるが、これをアプリ内のユーザー名と紐づけする方法を考えてみた。簡単そうだが、意外にはまってしまった。結果的には、以下のようにすることで解決できたが、ここに至るまでは、試行錯誤が必要だった。

<View側>

usertmpl3=list(map(lambda ob:{'customerid':ob.customerid,'username':ob.username},User.objects.all()) )          

srclst=list(filter( lambda ob: ob.get('canceled_date',"")=="",list(result.body['subscriptions'])))

subscriptions=list(map( lambda ob : {'subsc':ob ,  'cid':next( filter(lambda ob2: ob2['customerid'].strip() == ob['customer_id'].strip() ,usertmpl3),{'customerid':"",'username':"削除"})['username'] } ,srclst ))

sng= datetime.datetime.strptime(nen1, "%Y/%m/%d")
eng=  datetime.datetime.strptime(nen2, "%Y/%m/%d")
sbdt=list(filter(lambda sd:datetime.datetime.strptime(sd['subsc']['start_date'], '%Y-%m-%d')>=sng and datetime.datetime.strptime(sd['subsc']['start_date'], '%Y-%m-%d')<= eng,subscriptions))          

注意点:usrtmpl3、srclstいずれも最後にlistを適用してある。こうしないと、うまく動作しない。(filter()関数の戻り値はgeneratorオブジェクトという記述がネット内にある。)

まわりくどい式になってしまった。もっとスマートな方法がありそうだが。値が存在しないときに「削除」という表示にしたかったので、nextを使ってみた。

<HTML>
sbdt=response.sbdt;
$('<p style=font-weight:bold;>ユーザー名  サブスクリプションID ~</p>').appendTo('.result');
for (var i in sbdt) {  
   $('<p>'+sbdt[i]['cid']+" "+sbdt[i]['subsc']['id'] ~ +'</p>').appendTo('.result');  }
       

2022年9月10日土曜日

高血圧の基準と降圧剤ビジネス

 https://president.jp/articles/-/61331?page=4

 高血圧の基準は年々きびしくなっている。なぜだろう?と思うことがあったが。何が本当なのか、よくわからない。高すぎても、低すぎてもよくないということは、確かかもしれない。

2022年9月7日水曜日

スイフトのエンジンが安定しない。イグニッションコイル交換

 10万kmはもつといわれているイグニッションコイルだが、なぜか、14万kmで2回目の交換。今回は寿命がくるのがはやい。プラグもまだなんとかなるはずなんだけれど。とりあえず、交換したら快調になった。あまりケチらず、少し高いイグニッションコイルを購入した。

Django 覚書11

 スクエアを利用してみる。

pip install squareup

APIの説明が膨大。和訳して読みこなす。

Ajaxで、サーバを動作させて(Viewに記述)なんとかできそうだ。

様々なIDが必要でかなり手間はかかるし、いろいろ工夫も必要なようだ。