or1ko's diary

日々を書きます

HTTPSのURLから本文を取得する方法

事前に、Wifiを使えるようにしておく。
Raspberry Pi Pico WとMicroPythonでWifiに接続する方法 - or1ko's diary

まず、httpfetch.pyというファイル名で下記を作成。
長くなったので別ファイルとして保存。

import usocket
import ssl

def fetch(url):
    try:
        proto, dummy, host, path = url.split("/", 3)
    except ValueError:
        proto, dummy, host = url.split("/", 2)
        path = ""

    port = 443
    if ":" in host:
        host, port = host.split(":", 1)
        port = int(port)

    ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM)
    ai = ai[0]

    s = usocket.socket(ai[0], ai[1], ai[2])
    try:
        s.connect(ai[-1])
        ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
        s = ctx.wrap_socket(s, server_hostname=host)

        s.write('GET')
        s.write(b" /")
        s.write(path)
        s.write(b" HTTP/1.0\r\nHost: ")
        s.write(host)
        s.write(b"\r\n")
        s.write(b"\r\n")

        l = s.readline()
        l = l.split(None, 2)
        status = int(l[1])
        while True:
            l = s.readline()
            if not l or l == b"\r\n":
                break
            if l.startswith(b"Transfer-Encoding:"):
                if b"chunked" in l:
                    raise ValueError("Unsupported " + l)
            elif l.startswith(b"Location:"):
                raise NotImplementedError("Redirects not yet supported")
        
        body = s.read()
        
    except OSError:
        raise
    finally:
        s.close()

    return body

本体側で下記のようにして利用する。

import httpfetch

body = httpfetch.fetch('https://www.example.com')
print(body)

本文が大きいとメモリ不足で失敗する。
その場合は、すべて取得せず一定のbyteごとに読み取るようにする。

下記の2つのページを参考に作成。
pycopy-lib/cpython-ussl/ussl.py at master · pfalcon/pycopy-lib · GitHub
pycopy-lib/urllib.urequest/urllib/urequest.py at master · pfalcon/pycopy-lib · GitHub

Raspberry Pi Pico WとMicroPythonでWifiに接続する方法

下記のページの「Software Development」の「Raspberry Pi Pico Python SDK」内に記載がある。
たまに使うと思い出せないので書いておく。
Raspberry Pi Documentation - Raspberry Pi Pico and Pico W

import network
from secret import SSID, PASSWORD

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

while(True):
    if(wlan.status() < 0 or wlan.status() >= 3) :
        break
    else :
        print('connecting...')
        utime.sleep(1.0)

#print(wlan.ifconfig())

別途、secret.pyを作成し、SSIDとPASSWORDを記載しておく。

SSID = '<ssid>'
PASSWORD = '<password>'

接続できたか確認のためにprint(wlan.ifconfig())で中身を見る。
SSIDやPASSWORDが誤っていると適当なIPアドレスが付与されたりする。

日付や時刻ではなく時間を扱う方法

日付や時刻ではなく時間を扱う方法

TimeSpanを使う

> [TimeSpan]"12:34"
Days              : 0
Hours             : 12
Minutes           : 34
Seconds           : 0
Milliseconds      : 0
Ticks             : 452400000000
TotalDays         : 0.523611111111111
TotalHours        : 12.5666666666667
TotalMinutes      : 754
TotalSeconds      : 45240
TotalMilliseconds : 45240000

"12:34"は時分と解釈するので、分秒にしたい場合は"00:12:34"とする必要がある。

なお、日付や時刻はDateTimeを使う。

> [DateTime]"12:34"

202331112:34:00

Mesure-CommandやGet-Dateがこれらの値を返す。

windows 11 の edge で IEモードを利用する方法(2021/08/23、edgeのVer. 92.0.902.78)

令和3年度予算書関連
上記サイトのXML版が見えなくて、
windows 11 のedge の IEモードで開く方法を手探りで見つけたのでメモ。

  1. 右上の「...(設定など」を選択し、「設定」を開き、「Internet Explorer モードでサイトの再読み込みを許可」を「許可」に設定
  2. 対象のページを表示
  3. 右上の「…(設定など)」のメニューに「Internet Explorerモードで再度読み込む」を選択

やり方が記載されたページがあったけれど、
その方法でできなくなっていたので、変化中かもしれない。

Jelly Proの思い出をつらつら

https://pc.watch.impress.co.jp/docs/column/ebook/1321127.html

Jelly 2の記事を見たので、昔、その一つ前のJelly Proを
メインで使ってい時代のことを思い出したのつらつら記載。

Jelly Proは、最初にkick startで見つけ、そこで購入した。
とにかく重いスマホを持ち歩くのが嫌でひび軽量なものを探していた。
当時、何度探してもSonyのかなり前のものが小型のモデルがあるくらいで、
期待するほど小さいスマホはなかった。

シンガポールからの船便で1月くらいかけて届いた。
当初は技適に通ってなかったが、その後通った。

バッテリーはなにもしてなくても1日もつかもたないかだった。
画面は小さくて、慣れても字を打ち間違えることがある。
特に真ん中の下フリック(たしか「ん」)が基本できないので、
そこは何度も押すことで対応していた。
外に出たときにブラウジングをどうしてもしたいときにしか
打ち込まないことにしていたのであまり頻度はなかったが。
基本的に外に出たときはスマホは使わないようにしていた。
ただ、「Google Map」は使いたくなることがあったが、
画面が小さすぎて地図を読み取るのがだいぶ困難だった。
旅行とかの場合は、別途タブレットやノートPCを持っていたので、
Jelly Proをテザリングして使っていた。

ジョギングのお供には随分役になった。
Pokemon Goを起動させながらジョギングしていが、
大体1時間くらいで電池が無くなる感じだった。
ジョギングに持ち運ぶには小さくて軽くてよかった。
音楽プレイヤーとしても軽量なのは良い。

書き起こしてみるとなにが良かったのだろうかという感じだが、
だいぶ気に入っていたこともあり、1台紛失したあとに、
もう1台買って使い続けた。

ただ、やはり小さすぎた。
その後、Rakuten Miniがあらわれたので、
そちらに移動して今は満足している。
Jelly Proのおかげか、Rakuten miniの画面サイズに文句を感じたことがない。
ブラウジングも「Google Map」も満足している。

記事をみたら、「Jelly 2」に切り替えたくもなったが、
2万円強するならば、Rakuten Miniから切り替えようとは思わない。
安くても切り替えようと思えないので、今はRakuten Miniがよい。

Rakuten Miniは、バッテリー増やしてほしいこととと、
利用しない楽天のアプリやGoogleのアプリをアンイストールさせてほしい。
専用のランチャーがそれほどアプリを置きやすくないので、
不要なランチャーを削除できるようにしてほしい。
とは思うけど、Rakuten Miniが気に入っている。

ファイアウォールの送信の規則をすべて無効化する方法

管理者でPowerShellのコンソールを起動し、下記を実行する。
ファイアウォール設定は、エクスポートしておいてからやる。

Get-NetFirewallRule -Direction Outbound | ? { $_.Enabled -eq $True } | % { Set-NetFirewallRule -Enabled False -Name $_.Name }

一つの規則を無効化するのにそこそこ時間がかかるため、
有効な規則のみでフィルタしている。

別途、ファイアウォールの送信規則の規定をブロックにすることで、
自端末からのすべての通信をブロックすることができると思われる。

ブラウザがどのポートを使うかしらべたくて試した。
TCP 443とUDP53を許可すればyoutubegoogleなどは利用できたが、
この記事を書こうと試したら、TCP 80の追加も必要だった。
UDP53は、名前解決に利用しているのだろうから、IPアドレスでのアクセスなら不要だと思われる。

クラス名とメソッド名を出力するカスタムDoclet

クラス名やそのメソッド一覧が取得したくてJavadocのカスタムDocletを思い出して、使ってみたが、以外と目的にたどり着けなかったため、記録を残す。

JDK 9 からカスタムDocletの作成方法が変更されたようだ。
Using the new Doclet API

SampleDoclet.java
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.tools.Diagnostic.Kind;

import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;

public class SampleDoclet implements Doclet {
  private Reporter rep;

  @Override
  public void init(Locale locale, Reporter reporter) {
    this.rep = reporter;
  }

  @Override
  public String getName() {
    // Docletの名前
    return "sampleDoclet";
  }

  @Override
  public Set<? extends Option> getSupportedOptions() {
    // このDoclet用の引数を定義する
    return Collections.emptySet();
  }

  @Override
  public SourceVersion getSupportedSourceVersion() {
    // サポートするソースコードのバージョン
    return SourceVersion.latest();
  }

  @Override
  public boolean run(DocletEnvironment docEnv) {

    Set<? extends Element> includedElements = docEnv.getIncludedElements();
    for (Element element : includedElements) {
      if (element.getKind() == ElementKind.CLASS) {
        rep.print(Kind.NOTE, "クラス名 -> " + element.getSimpleName().toString());
        List<? extends Element> members = element.getEnclosedElements();
        for (Element member : members) {
          if (member.getKind() == ElementKind.METHOD) {
            rep.print(Kind.NOTE, "メソッド名 -> " + member.toString());
          }
        }
      }
    }
    return true;
  }
}
実行結果
> javac SampleDoclet.java -encoding utf8
> javadoc SampleDoclet.java -sourcepath . -doclet SampleDoclet -docletpath . -encoding utf-8
ソース・ファイルSampleDoclet.javaを読み込んでいます...
Javadoc情報を構築しています...
クラス名 -> SampleDoclet
メソッド名 -> init(java.util.Locale,jdk.javadoc.doclet.Reporter)
メソッド名 -> getName()
メソッド名 -> getSupportedOptions()
メソッド名 -> getSupportedSourceVersion()
メソッド名 -> run(jdk.javadoc.doclet.DocletEnvironment)