2020年10月19日月曜日

DUNSナンバー登録申請

 個人事業者でも登録可能です。FAQを見ると、屋号の入った通帳があればよさそうです。また、登録申請のWEB画面でも、FAXのない方は、xxxを入れろと親切です。しかし、書類は、なぜかFAXで送る必要があります。コピー機にFAXはついていますが、電話線を引き込むのも面倒なので、秒速FAXを導入しました。送信Onlyでもよく、ポイントチャージ制で、200円からチャージできます。これで十分です。

2020年10月18日日曜日

コードサイニング

コードサイニングとは

 https://qiita.com/Chitama/items/915abc7b872b1e086800

認証局情報

https://www.nda.co.jp/memo/codesigning/index.html

ということで、申請の前にDUNS登録とDomain整備が必要になります。


Domainは、4つ所持しているのですが、名前が載っているドメインは、長年使っていたドメインであり、そのドメインの管理業者と連絡がつかなくなっていました。

消費者センタ、総務省等、手を尽くしましたが、結局届け出のTELにも出ないということで埒が明かず、カナダの上位管理会社(Registrar)と交渉し、ようやくAuthCodeを出してもらい、ドメインを移転することが出来ました。ドメインは移転したのですが、WEBデータ等整備していなかったので、コピーしメールサーバ設定その後DNSを切り替えてドメインの完全切り替え完了となります。従い、

1)DUNS登録

2)Domain整備 whois情報更新

(怪我の功名なのですが、最近は個人情報をさらさなくても独自ドメイン出来ますよ、と謳っている業者さんもあるのですが、名前をさらすことが証明につながる場合もあるということです。)

3)申請

コールバックは、夜中に英語で起こされるのはたまらないので、日本の代理店にしようと思います。

4)コールバック


を経て、ようやくコードサイニングが完了する予定です。その間に、MSIX用のコードに変更する作業を行います。

11月EndにMSIX版に移行を目指そうと思います。


2020年10月17日土曜日

MSIX

 今までインストール時の残念なメッセージが出るのを防止するには、ストアアプリ化するしかないと思っていたのですが、その認識は間違いであることが分かりました。MSIXという新し形式を使い、別にコードサイニングを取得すれば、ストアアプリ化する必要はないことが分かりました。今後の方針としては、

■インストーラをMSIXにする

■コードサイニングを取得維持する

■ソフト本体は無料とする (ライセンス期限を撤廃します)

■Win10 64bit版のみサポート(ビルド1903以降)

しようと思います。MSIX化後は、制約設定・メンテナンス・サポート・コンサルティングが必要な方のみ有償とする予定です。ストアアプリ化はキャンセルします。

MSIXについては、マイクロソフトのビデオを見ながら勉強しているのですが、出てくるエンジニアの方は、Nativeと思われる方はむしろ少なく、インド・フランスその他多様な人達が働いている、米国は本当に懐の深い国だと思いました。

この年にして、AWS LAMBDA, Docker, MSIX と次々に新しい技術を習得しています。最も役立っているのは、Qiitaですが、最後は、やはりStackOverflow 等の英語情報に行き着きます。  



2020年10月16日金曜日

国際祝日対応再び

前に書いた祝日ライブラリは、振り替え休日が定義されていないことが分かってドロップしました。そこで、下記で言及されているライブラリを採用することにしました。

ただし、javascriptなので、C#では、そのままでは、動作しません。そこで、
次のように、オフラインで、2035年までJSONを吐かせてそれをファイルとして搭載することにしました。
#!/usr/bin/env node

/**
 * draw tree of supported countries, states, regions
 */
function country_draw(stream,hd,country,country_name,state,state_name,region,region_name){
  hd.init(country)
    
    var holidays=hd.getHolidays(2015)
    for (y=2016;y< 2035 -="" 10="" 1="" :="" console.dir="" console.log="" const="" countries="" countrieslen="" country="" country_code="" country_name="" d="" date-holidays="" date="" draw="[" dt.getdate="" dt.getmonth="" dt="new" else="" for="" foreach="" function="" hd="new" holiday.substitute="" holiday.type="=" holiday="" holidays1="hd.getHolidays(y)" holidays="" i="" if="" m="" maxarraylength:="" maxarraylength="" msec="" n="" null="" object.keys="" of="" ountries:="" public="" public_holidays.push="" public_holidays="" region="" region_code="" region_name="" slice="" state="" state_code="" state_name="" str="" stream="" substitute_holidays.push="" substitute_holidays="" t="" tree="" util.inspect="" util="" var="" y="dt.getFullYear();"> {
    const d = (i === countriesLen ? draw[1] : draw[0])
    //console.log(d + country + ': ' + countries[country] + '\n')
    const hd = new Holidays()
    if (i!=0) console.log(",");
    country_draw(stream,hd,country,countries[country],"","","","")
    const states = Holidays().getStates(country)
    if (states) {
      const statesLen = Object.keys(states).length - 1
      Object.keys(states).forEach((state, j) => {
        let d = (i === countriesLen ? draw[3] : draw[2])
        d += (j === statesLen ? draw[1] : draw[0])
        //console.log(d + state + ': ' + states[state] + '\n')
        console.log(",");
   	country_draw(stream,hd,country,countries[country],state,states[state],"","")

        const regions = Holidays().getRegions(country, state)
        if (regions) {
          const regionsLen = Object.keys(regions).length - 1
          Object.keys(regions).forEach((region, k) => {
            let d = (i === countriesLen ? draw[3] : draw[2])
            d += (j === statesLen ? draw[3] : draw[2])
            d += (k === regionsLen ? draw[1] : draw[0])
            //console.log(d + region + ': ' + regions[region] + '\n')
	console.log(",");
   	country_draw(stream,hd,country,countries[country],state,states[state],region,regions[region])

          })
        }
      })
    }
  })
}
module.exports = tree

if (module === require.main) {
    console.log("{'members':[\n")
  tree(process.stdout)
  console.log("]\n")
  console.log("}\n")
}

定義済み曜日の祝をクリックするとComboboxが出現します。
国だけではなくて、米国のようにState、さらにRegionまで必要な場合もあるんですね。

2020年10月15日木曜日

UI Debug

 API Gateway呼び出しでは、慣れないawait/asyncを使っています。その際、UIでのデバッグでは、こちらを参考にしています。

https://qiita.com/ken_hamada/items/501b164374667319d270

A)背景の一番後ろが、DebugViewというツールで、C#のデバッグ出力です。
B)2番目が、UIをループされているプログラムで、上記サイトの電卓操作のプログラムを改造してスケジュールナース用の求解ボタンを叩いています。AWSのLambdaのコールドスタートタイミングに絡んでいそうなので、数分待って叩くループにしています。
C)3番目が、同作者のツールでAutomationIDを拾ってくれます。開発環境はリモートデスクトップでつながった、マイクもDisplayもないマシンでそのままでは、動かなかったので、音声入力のC#ソースは、カットしています。

なぜか、リモートデスクトップを最小化するとスリープに入るためか、B)がクラッシュしてしまいます。が、最小化しないで、画面の片隅に置いておけば大丈夫なようです。


2020年10月14日水曜日

Grammerly Premium を導入

 今まで無料版を使っていたのですが、Premiumに移行しました。DeepLとの併用で、かなり作業効率がよさそうです。楽しく英文を添削してくれます。






練習を兼ねてSDK2.1 Nurse Scheduling Solver AWS Lambda Engineの動画を作ってみました。

https://www.youtube.com/watch?v=UBkmB0LYVUc&feature=youtu.be

2020年10月13日火曜日

REST API検討

 APIを構築して、それに対してサービスを構築するというのが、一般的なのでしょうが、今回は、そのアプローチは採っていません。真にユーザの利便を考えたときに、Lambdaが直接呼べる環境があるのであれば、直接呼んで頂いた方が良いと信じるからです。顧客毎のクローズドな世界となり顧客毎の対応が必要となりますが、何かトラブルがあっても他のお客さまは、影響を受けないというメリットもあります。

ということで、APIGatewayを敢えて構築する必要はない訳ですが、AWS外から呼ぶとすれば、APIGatewayを介することは必須であります。アカウントIDとSecretKeyをプログラムにぶち込んでAWS外からダイレクトに呼ぶことも不可能ではありませんが、アカウント情報をそのような形で入れることは、危険極まりない行為です。ハッカには太刀打ちできません。

SDKサンプルとして構築してみました。API-Gatewayは、初めてでしたが、3日位で動くようになりました。その際、REST APIについて調べてみました。

https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa

https://qiita.com/masato44gm/items/dffb8281536ad321fb08

https://qiita.com/mserizawa/items/b833e407d89abd21ee72


2020年10月12日月曜日

newtonsoft C# problem.jsonのダイエット

 AWS Lambda非同期コールや、AWS STEP FUNCTIONでは、payloadサイズが256KB程度に制限されています。具体的には、ソルバーに投げるpayload sizeがこのサイズを超えているとLambdaに届くまえにはじかれてしまいます。SC3GUIでは、1MBのproblem.jsonも普通にありえるので、なるべくこのサイズが、256KB以下になるようにすることが目的です。(サイズを超えたらS3を使います。DynamodbでもItemSizeが制限されているので不適です。)

SC3 GUIでは、Jsonのシリアライザにnewtonsoftを使っています。このオプションを使うことで、ある程度ダイエットが可能です。

<方法1 インテンドなしにする>
#if REDUCE_JSON
            Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings { Converters = { new CustomDateTimeConverter() },Formatting = Newtonsoft.Json.Formatting.None };
#else
             Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings { Converters = { new CustomDateTimeConverter() },Formatting = Newtonsoft.Json.Formatting.Indented };//, Forma
#endif


こうすると、読みやすいJSONが

{
  "SO": {
    "name": "Shift Objects",
    "members": [
      {
        "use": true,
        "name": "ShiftDef",
        "def_name": "日勤",
        "auto_schedule": true,
        "color": "LightGray",
        "label": "・",
        "another_labels": [
          "",
          ""
        ],

読みにくくなります。これが一番効果がありました。

{"SO":{"name":"Shift Objects","members":[{"use":true,"name":"ShiftDef","def_name":"日勤","auto_schedule":true,"color":"LightGray","label":"日","another_labels":["",""],"another_colors":

<方法2 default valueを使う。defaultの値を定義しておいて、それと同じだったらJSON化されません。> 方法1と2を用いることで、サイズが1/4から1/5程度になりました。

#if REDUCE_JSON
        [ DefaultValue("")]//OCT042020
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
#endif
        public string shift;
        //OCT042020
#if REDUCE_JSON
        [DefaultValue(0)]
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public int level;
#endif

2020年10月11日日曜日

API GATEWAY  Single Quote でServer Error を対策


Jsonペイロード中にあってはいけないのか、よく分かっていませんが、例えば、Pythonのコードのように、PythonコードがあるとSingleQuoteが発生します。 newtonsoftでこれをシリアライズていますが、Escapeしてくれません。そのままPayloadに乗ってAPIGateway通過時にServerErrorとなるようです。
import sc3
sc3.print('Hello Python3 Constraint World!\n')

そこで、PythonのREST API デモコードでは、次のようにしました。
json_open = open('problem.json', 'r') #Read problem.json file
json_load = json.load(json_open)#conver to dictionary

json_load["SolP"]["external_constraint_python"]=json_load["SolP"]["external_constraint_python"].replace('\'','\"') #Web API seems to reject Single Quote 

import sc3
sc3.print('Hello Python3 Constraint World!\n')

C# REST API デモコードでは、安直にDoubleQuoteのEsaceとしました。
 string rep_str = problem_server_string.Replace("'", "\\\"");//API Server dislikes ' 

2020年10月10日土曜日

AWS Lambda Broken Pipe

REST APIを作成中、S3や、DyanamodbをC++でいじっていて、上記のエラーが不定期にでてLambdaがクラッシュしてしまいます。(下図で、API Gateway後のLambda)





原因は良く分かっていないのですが似た症状のレポートがありました。

https://github.com/aws/aws-sdk-cpp/issues/959

これによれば、

options.HttpOptions.installSigPipeHandler = true;


にするとのこと。SDK sampleでもそのようなcodeにはなっていないのですが、なぜか

上記の通りするとクラッシュが収まりました。

2020年10月2日金曜日

Linux Time 変換

AWS Lambdaのライセンスは、LinuxTimeで行うことにしました。

なので、LinuxTime(64bit)と日付との相互変換が必要になります。

 ありました。

https://tool.konisimple.net/date/unixtime

2020年10月1日木曜日

AWS API GATEWAYでARNを暴露しない

 AWS LAMBDA は、内から呼ぶ分には、CREDENTIAL情報は、必要なく適当なIAMを設定してやれば、ACCESSIDをプログラムコードに入れる必要はありません。たとえば、

https://qiita.com/itoa06/items/614fc3322f83512cab3b

<LAMBDAをAPI GATEWAYから呼ぶときの問題>

問題は、API GATEWAYのタイムアウトが29secです。LAMBDAがこの時間内に解ける保証はありません。そこで、STEP FUNCTIONを使用して、API GATEWAYのタイムアウトを避けつつ、LAMBDAの解の到着をポーリングで待ちます。

https://dev.classmethod.jp/articles/apigateway-stepfunctions-asynchronous/

上記の手法で、実装してみました。StepFUNCTION StartExecutionでLAMBDAをFireし、DescribeExecutionでポーリングします。

<StartExecution とDescribe Executionの問題>

ところが、上記そのままですと、ARNが暴露されてしまいます。

<解決策>

ありました。下記です。

https://medium.com/@cody_green/using-aws-api-gateway-and-step-functions-without-exposing-your-arn-ce94a88fa594