Tx見るやつのコード

Tx見るやつのコード

ツイッターにアップしたこれです。「Tx見るやつのコード」というタイトルなので、いきなりコード置きます。ちょっとした説明は下に。

// 必要なライブラリ
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <WebSocketsClient.h>
#include <ArduinoJson.h>
#include <TFT_eSPI.h>
#include <math.h>

// WiFi情報
const char* ssid = "入れてね";
const char* password = "入れてね";

// 表示と接続用
TFT_eSPI tft = TFT_eSPI();
WebSocketsClient webSocket;

// 消失点(画面中央上)
const int vanishX = 240 / 2;
const int vanishY = 30;

// 最新トランザクションの省略ハッシュ
String latestTxHashShort = "";

// 投影関数(Z中心固定型)
void project(int x, int y, float zOffset, int &outX, int &outY) {
  float scale = 1.0 / (1.0 + zOffset / 100.0); // 固定Z中心 = 100px 奥
  outX = vanishX + (x - vanishX) * scale;
  outY = vanishY + (y - vanishY) * scale;
}

// トランザクションデータ構造
struct Tx {
  float btc;
  float x;
  int size;
  String label;
};

#define MAX_TXS 20
Tx txs[MAX_TXS];
int txCount = 0;

unsigned long lastUpdate = 0;
const int screenWidth = 240;
const int screenHeight = 135;
const float speed = 30.0 / 1000.0; // ピクセル毎ミリ秒

// 立方体を描画する関数
void drawCube(int x, int y, int size) {
  float centerZ = 60.0;
  float halfSize = size / 2.0;

  // 立方体の8点 (x,y,z)
  int px[8], py[8];
  float cx = x + halfSize;
  float cy = y + halfSize;

  float vx[8] = {
    -halfSize, +halfSize, +halfSize, -halfSize,
    -halfSize, +halfSize, +halfSize, -halfSize
  };

  float vy[8] = {
    -halfSize, -halfSize, +halfSize, +halfSize,
    -halfSize, -halfSize, +halfSize, +halfSize
  };

  float vz[8] = {
    -halfSize, -halfSize, -halfSize, -halfSize,
    +halfSize, +halfSize, +halfSize, +halfSize
  };

  for (int i = 0; i < 8; i++) {
    int sx, sy;
    project(cx + vx[i], cy + vy[i], centerZ + vz[i], sx, sy);
    px[i] = sx;
    py[i] = sy;
  }

  const int edges[12][2] = {
    {0,1},{1,2},{2,3},{3,0},
    {4,5},{5,6},{6,7},{7,4},
    {0,4},{1,5},{2,6},{3,7}
  };
  for (int i = 0; i < 12; i++) {
    tft.drawLine(px[edges[i][0]], py[edges[i][0]], px[edges[i][1]], py[edges[i][1]], TFT_WHITE);
  }
}

// 新しいトランザクションを追加
void addTx(float btc) {
  if (txCount >= MAX_TXS) return;

  float size = cbrt(btc) * 40.0;
  if (size < 1.0) size = 1.0;

  Serial.print("Adding tx: ");
  Serial.print(btc, 8);
  Serial.print(" BTC, size: ");
  Serial.println(size);

  txs[txCount].btc = btc;
  txs[txCount].x = 0;
  txs[txCount].size = (int)size;
  txs[txCount].label = String(btc, 8);
  txCount++;
}

// WebSocket イベント
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
  switch (type) {
    case WStype_DISCONNECTED:
      Serial.println("[WebSocket] Disconnected");
      break;
    case WStype_CONNECTED:
      Serial.println("[WebSocket] Connected to server, sending sub msg...");
      webSocket.sendTXT("{\"op\":\"unconfirmed_sub\"}");
      break;
    case WStype_TEXT: {
      Serial.println("[WebSocket] Message received");
      Serial.println((char*)payload);

      DynamicJsonDocument doc(2048);
      DeserializationError error = deserializeJson(doc, payload);
      if (error) {
        Serial.print("deserializeJson failed: ");
        Serial.println(error.f_str());
        return;
      }

      if (doc["op"] == "utx") {
        JsonArray inputs = doc["x"]["inputs"];
        long total = 0;
        for (JsonObject input : inputs) {
          total += input["prev_out"]["value"] | 0;
        }
        float btc = total / 100000000.0;
        addTx(btc);

        // ハッシュを省略形で保存
        const char* fullHash = doc["x"]["hash"];
        if (fullHash && strlen(fullHash) >= 8) {
          String hashStr(fullHash);
          latestTxHashShort = hashStr.substring(0, 4) + "..." + hashStr.substring(hashStr.length() - 4);
        }
      }
      break;
    }
    default:
      break;
  }
}

// 初期化
void setup() {
  Serial.begin(115200);
  randomSeed(analogRead(0));

  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setTextDatum(MC_DATUM);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected");

  webSocket.beginSSL("ws.blockchain.info", 443, "/inv");
  webSocket.onEvent(webSocketEvent);
  webSocket.setReconnectInterval(5000);
}

// トランザクションを描画
void drawTxs() {
  Serial.println("Drawing frame...");
  tft.fillScreen(TFT_BLACK);
  for (int i = 0; i < txCount; i++) {
    Tx& tx = txs[i];
    int y = (screenHeight - tx.size) / 2 + 30;
    drawCube((int)tx.x, y, tx.size);
  }

  if (txCount > 0) {
    tft.setCursor(0, 0);
    tft.setTextFont(2);
    tft.setTextColor(TFT_WHITE, TFT_BLACK);
    tft.print(txs[txCount - 1].label);
    tft.setCursor(0, 16);
    tft.print(latestTxHashShort);
  }
}

// トランザクション位置更新
void updateTxs(unsigned long delta) {
  float dx = speed * delta;
  int writeIndex = 0;
  for (int i = 0; i < txCount; i++) {
    txs[i].x += dx;
    if (txs[i].x < screenWidth + txs[i].size * 2) {
      txs[writeIndex++] = txs[i];
    }
  }
  txCount = writeIndex;
}

// メインループ
void loop() {
  webSocket.loop();
  unsigned long now = millis();
  unsigned long delta = now - lastUpdate;
  if (delta >= 30) {
    updateTxs(delta);
    drawTxs();
    lastUpdate = now;
  }
}

(blockchain.infoからデータ読んでるだけですね)

Arduino IDEで書き込みます。基本的に最初のライブラリを入れるだけで動くと思いますが、ディスプレイ設定がハマりポイントです。TFT_eSPIディレクトリのUser_Setup_Select.hを直接いじって(コメントアウトしたり消したりするだけ)合うディスプレイを選びます。ここをうまくやらないと画面サイズが合わなかったり、ノイズ領域が出たり、白黒反転したり、90度回転したりします。もしかしたら上のコードにもちょっとした修正が必要になるかもしれません。ここは工夫して下さい。User_Setup.h はいじらなくて良かった気がするうろ覚え。

ハードウェア

あんまり詳しくないけどなんでもいいんだと思います。ディスプレイくっついてるのが楽です。こんなやつ。くっついてなくてもいいと思う。

ディスプレイ設定に話を戻しますが、商品ページのどこを見てもディスプレイの種類がわからなったりするので、レビュー欄見ると誰か書いててくれてたりします。

ビバ!🍊

ここより下は何もありません。Tip me!

この続き : 11字 / 画像 0枚
390

会員登録 / ログインして続きを読む

関連記事

記事を書いた人

SNSにシェア

このクリエイターの人気記事

ビットコインのETF承認 - 裸の王様の新しい衣装

77