조명비 지급(제2부)

56179 단어 iotblockchain
이 강좌는 1부터 시작하여 1부를 찾을 수 있습니다. 이 강좌를 읽기 전에 이 강좌를 먼저 읽으십시오.

7단계:Api 설정


api의 코드는 here을 찾을 수 있습니다.이 폴더를 다운로드하고 npmruninstall을 실행하기만 하면 됩니다.다음 몇 절에서api의 주요 파일을 소개할 것입니다.

8단계: TextHelper


TextHelper 클래스는 얽힌 정보를 저장하는 데 도움을 주는 도움말 함수를 포함합니다.
/**
 * Helper functions for use with text.
 */
export class TextHelper {
}
encodeNonASCII 함수는 비 ASCII 문자를 이스케이프 문자로 인코딩합니다.
/**
     * Encode Non ASCII characters to escaped characters.
     * @param value The value to encode.
     * @returns The encoded value.
     */
    public static encodeNonASCII(value: string): string | undefined {
        return typeof (value) === "string" ?
            value.replace(/[\u007F-\uFFFF]/g, chr => `\\u${(`0000${chr.charCodeAt(0).toString(16)}`).substr(-4)}`)
            : undefined;
    }
decodeNonASCII 함수는 이스케이프 문자를 비 ASCII 문자로 디코딩합니다.
/**
     * Decode escaped Non ASCII characters.
     * @param value The value to decode.
     * @returns The decoded value.
     */
    public static decodeNonASCII(value: string): string | undefined {
        return typeof (value) === "string" ?
            value.replace(/\\u([\d\w]{4})/gi, (match, grp) => String.fromCharCode(parseInt(grp, 16))) :
            undefined;
    }

단계 9: TrytesHelper


필요한 기능이 TrytesHelper class으로 가져왔습니다.이것은 대상을trytes로 변환하고trytes를 대상으로 변환하는 데 도움이 될 것입니다.만약 우리가 산열을 생성해야 한다면, 우리는 주어진 산열을 생성하는 함수를 만들 것이다.
import { asciiToTrytes, TRYTE_ALPHABET, trytesToAscii } from "@iota/converter";
import * as crypto from "crypto";
import { TextHelper } from "./textHelper";
create 클래스는 모든trytes 작업을 처리하는 데 도움을 줍니다.
/**
 * Helper functions for use with trytes.
 */
export class TrytesHelper {

}
toTrytes 함수는 객체를 trytes로 변환합니다.
/**
     * Convert an object to Trytes.
     * @param obj The obj to encode.
     * @returns The encoded trytes value.
     */
    public static toTrytes(obj: unknown): string {
        const json = JSON.stringify(obj);
        const encoded = TextHelper.encodeNonASCII(json);
        return encoded ? asciiToTrytes(encoded) : "";
    }

fromTrytes 함수는 trytes를 주어진 대상으로 변환합니다.
/**
     * Convert an object from Trytes.
     * @param trytes The trytes to decode.
     * @returns The decoded object.
     */
    public static fromTrytes<T>(trytes: string): T {
        if (typeof (trytes) !== "string") {
            throw new Error("fromTrytes can only convert strings");
        }

        // Trim trailing 9s
        const trimmed = trytes.replace(/\9+$/, "");

        if (trimmed.length === 0) {
            throw new Error("fromTrytes trytes does not contain any data");
        }

        const ascii = trytesToAscii(trimmed);
        const json = TextHelper.decodeNonASCII(ascii);
        return json ? JSON.parse(json) : undefined;
    }
generateHash 함수는 제공된 길이를 위해 무작위 해시를 생성합니다.
  /**
     * Generate a random hash.
     * @param length The length of the hash.
     * @returns The hash.
     */
    public static generateHash(length: number = 81): string {
        let hash = "";

        while (hash.length < length) {
            const byte = crypto.randomBytes(1);
            if (byte[0] < 243) {
                hash += TRYTE_ALPHABET.charAt(byte[0] % 27);
            }
        }

        return hash;
    }

단계 10: MQTT


다음 코드를 사용하여 필요한 파일을 가져왔습니다.하나는 Mqtt 라이브러리입니다.다른 하나는 프로필입니다.
import mqtt from "mqtt";
import config from "../data/config.local.json";
MqttHelper 클래스는 모든 Mqtt 함수를 처리합니다.
/**
 * Class to handle Mqtt functions
 */
export class MqttHelper {
}
이 클래스에서 변수를 설정했습니다. 이 변수들은 Adafruit IO의 Mqtt와 연결된 프로필을 나타냅니다. Adafruit IO는 구름 속의 에이전트와 같습니다.이것은 아래의 코드를 사용하여 완성한 것이다.
/**
     * The mqtt client
     */
    protected _mqttClient: mqtt.MqttClient;

    /**
     * The mqtt host
     */
    protected readonly _host: string;

    /**
     * The username for the mqtt host/broker
     */
    protected readonly _username: string;

    /**
     * The password for the mqtt host/broker
     */
    protected readonly _password: string;

    /**
     * The feed/topic to subscribe to
     */
    protected readonly _feed: string;

    /**
     * The port to use when connecting to the mqtt host/broker
     */
    protected readonly _port: number;


구조 함수에서, 우리는 변수를 설정 파일에 저장된 값으로 설정합니다.
constructor() {
        this._mqttClient = null;
        this._host = `mqtts://${config.MQTT_CONFIG.ADAFRUIT_IO_URL}`;
        this._username = config.MQTT_CONFIG.ADAFRUIT_USERNAME;
        this._password = config.MQTT_CONFIG.ADAFRUIT_IO_KEY;
        this._feed = `${config.MQTT_CONFIG.ADAFRUIT_USERNAME}/f/${config.MQTT_CONFIG.ADAFRUIT_IO_FEEDNAME}`;
        this._port = config.MQTT_CONFIG.ADAFRUIT_IO_PORT;
    }
그리고 에이전트에 연결하는 데 도움을 줄 함수를 만들었습니다.이 경우 Adafruit IO.
 /**
   * Function to connect to a mqtt host/broker and subscribe to events coming from it
   */
public connect(): void {

}
사용자 이름, 비밀번호, 사용할 포트를 사용하여 클라우드 에이전트에 연결합니다.
// Connect mqtt with credentials (in case of needed, otherwise we can omit 2nd param)
        this._mqttClient = mqtt.connect(
            this._host, { username: this._username, password: this._password, port: this._port });
오류가 발생하면 오류를 기록하고 연결을 끊기를 원합니다.
 // Mqtt error calback
        this._mqttClient.on("error", err => {
            console.log(err);
            this._mqttClient.end();
        });
만약 우리가 연결에 성공한다면, 우리는 우리의 컴퓨터가 성공적으로 연결되었다는 메시지를 인쇄할 것이다.
// Connection callback
        this._mqttClient.on("connect", () => {
            console.log(`mqtt client connected`);
        });
우리는 연결하고 구독할 요점을 지정합니다.
// mqtt subscriptions
        this._mqttClient.subscribe(this._feed);
만약 우리가 소식을 받게 된다면, 우리는 받은 소식만 표시할 것이다.
  // When a message arrives, console.log it
        this._mqttClient.on("message", message => {
            console.log(message.toString());
        });
닫을 때, 우리는 Mqtt 클라이언트만 닫을 것입니다.
this._mqttClient.on("close", () => {
            console.log(`mqtt client disconnected`);
        });
우리는 메시지를 qtt에 발표하는 데 사용할 다른 함수를 만들었습니다.
 /**
     * Function  to send messages to the mqtt client/broker
     * @param message The message to be sent
     */
    public sendMessage(message: string | Buffer): void {
        this._mqttClient.publish(this._feed, message);
    }

11단계: MAM


필요한 라이브러리를 가져옵니다.
import { composeAPI } from "@iota/core";
import { createChannel, createMessage, mamAttach } from "@iota/mam.js";
import fs from "fs";
import config from "../data/config.local.json";
import { INodeConfiguration } from "../models/configuration/INodeConfiguration";
import { TrytesHelper } from "./trytesHelper";
MamHelper라는 클래스를 만들었습니다. 이 클래스는 Mam 채널에 연결하는 데 도움을 줍니다.
export class MamHelper {
}
여기서 사용할 노드의 설정 설정을 가져옵니다.
/**
  * Node configuratin settins
  */
  private readonly _nodeConfig: INodeConfiguration;

  constructor() {
       this._nodeConfig = config.node;
   }
우리는 mam 채널에 메시지를 저장할 함수를 만들었습니다.
/**
 * Function to store information on the mam channel
 * @param asciiMessage The message to be stored on the mam channel
 */
public async create(asciiMessage: object): Promise<void> {
}
그리고mam 채널에 메시지를 저장하는 전체 과정이 실패하면try-catch를 만들어서 오류를 포착합니다.
try {

} catch (error) {
            throw new Error(`Could not store the message on the mam channel ${error} `);
}
그런 다음 채널 상태를 로드하고 해석해 보겠습니다.
 let channelState;

            // Try and load the channel state from json file
            try {
                const currentState = fs.readFileSync("./channelState.json");
                if (currentState) {
                    channelState = JSON.parse(currentState.toString());
                }
            } catch (e) { }
채널 상태를 로드할 수 없으면 새 채널 상태를 만듭니다.
// If we couldn't load the details then create a new channel.
if (!channelState) {

    // set up details for the channel
    const mode = "public";

    // create a new mam channel
    channelState = createChannel(TrytesHelper.generateHash(81), 2, mode);
}
채널 상태를 사용하여 Mam 메시지를 만듭니다.
// Create a MAM message using the channel state.
const mamMessage = createMessage(channelState, TrytesHelper.toTrytes(asciiMessage));
그리고 mam 채널 정보를 표시합니다.
// Display the details for the MAM message.
console.log("Seed:", channelState.seed);
console.log("Address:", mamMessage.address);
console.log("Root:", mamMessage.root);
console.log("NextRoot:", channelState.nextRoot);
제공 프로그램의 노드 설정을 설정합니다.
 const iota = composeAPI({
          provider: this._nodeConfig.provider
 });
그리고 메시지를 맥 채널에 추가합니다.
// Attach the message.
console.log("Attaching to tangle, please wait...");

await mamAttach(iota, mamMessage, this._nodeConfig.depth, this._nodeConfig.mwm);
우리는 Mam 채널에서 온 모든 정보를 볼 수 있는 링크를 제공했다.
console.log(`You can view the mam channel here https://utils.iota.org/mam/${mamMessage.root}/devnet`);

그리고 Mam 채널 json 파일의 상태를 저장합니다.
 // Store the channel state.
 try {
         fs.writeFileSync("./channelState.json", JSON.stringify(channelState, undefined, "\t"));
 } catch (e) {
         console.error(e);
 }

12단계: 사물인터넷 결제


우리는 프로젝트를 위해 필요한 라이브러리와 파일을 가져옵니다.
import bodyParser from "body-parser";
import express from "express";
import paymentModule from "iota-payment";
import scheduler from "node-schedule";
import { MamHelper } from "./utils/mamHelper";
import { MqttHelper } from "./utils/mqttHelper";
그리고 express 서버를 설치했습니다.
const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
qttHelper 함수를 가져옵니다.그리고 우리는 연결합니다. 우선 "닫기"메시지를 보내서 계전기를 닫습니다.
const mqttClient = new MqttHelper();
mqttClient.connect();
mqttClient.sendMessage("OFF");
그리고 결제 모듈에 대한 옵션을 설정합니다.이는api 옵션, 대시보드 옵션, 웹 플러그인 옵션과 관련이 있습니다.
const options = {
    api: true,
    dashboard: true,
    websockets: true
};
express 서버를 설정하고 실행합니다.이것은 우리에게 두 개의 노선을 제공했다./iotapay 루트와/iotapay/api 루트.
const server = paymentModule.createServer(app, options);

// Start server with iota-payment dashboard on '/iotapay' and api on '/iotapay/api'
server.listen(5000, () => {
    console.log(`Server started on http://localhost:5000 `);
    console.info(`Please visit http://localhost:5000/iotapay in your browser`);
});
현재 날짜와 시간을 반환하는 시간 변수를 설정합니다.
const time = () => {
    return new Date();
};
그리고 우리는 지불 처리 프로그램을 만들었다.지불이 성공하면 지불 처리 프로그램을 호출할 것이다.
//Create an event handler which is called, when a payment was successful
const onPaymentSuccess = async payment => {
}
우리는 모든 지불 정보를 변수에 저장할 것이다.이것은 지불 사건 자체도 포함한다.
const transaction = {
        paid: payment.paid,
        type: payment.type,
        value: payment.value,
        address: payment.address,
        index: payment.index,
        id: payment.id,
        txInfo: {
            timestamp: payment.txInfo.timestamp,
            hash: payment.txInfo.hash,
            value: payment.txInfo.value,
            message: payment.txInfo.message
        },
        event: [`User has paid ${payment.txInfo.value} tokens for lights`]
    };
mam 채널을 설정하고 메시지를 만듭니다.
const mamHelper = new MamHelper();

await mamHelper.create(transaction);
그리고 우리는 3초를 기다렸다가 불을 켜고 모든 업무를mam 채널로 보내는 시간을 추가했다.
setTimeout(async () => {
        // send the event that the lights are now on
        transaction.event.push(`Lights are on ${time()}`);
        await mamHelper.create(transaction);

        // tslint:disable-next-line: align
    }, 3000);
조명이 켜지는 시간(분 단위)을 사물인터넷 영패 수량에 60000을 곱해 봅시다.
 const seconds: number = payment.txInfo.value * 60000;
시작 시간과 종료 시간을 설정하면 불이 켜집니다.
 const startTime = new Date(Date.now());
 const endTime = new Date(startTime.getTime() + seconds);
불이 켜져 있는 것을 유지하기 위해서, 우리는 설정된 시간 내에 10초마다 Mqtt 메시지를 보냅니다.
await scheduler.scheduleJob({ start: startTime, end: endTime, rule: `*/10 * * * * *` }, () => {
        mqttClient.sendMessage("ON");
        console.log("😊");
   });
일단 시간이 끝나면 종료 메시지를 보내는 종료 시간을 설정합니다.
 const newEndTime = new Date(endTime.getTime() + 30000);
우리는 계전기가 끊어지는 것을 확보하기 위해 10초, 30초 동안 끊기는 메시지를 다시 보냈다.
await scheduler.scheduleJob({ start: endTime, end: newEndTime, rule: `*/10 * * * * *` }, () => {
        mqttClient.sendMessage("OFF");
        console.log("😐");
    });
그리고 우리는 즉시 맵 채널에 표시등이 꺼졌다는 메시지를 보냅니다.
await scheduler.scheduleJob({ start: endTime, end: newEndTime, rule: `*/30 * * * * *` }, async () => {

        // send the event that the lights are now off
        transaction.event.push(`Lights are off ${time()}`);
        await mamHelper.create(transaction);
    });
마지막으로, 우리는 방금 만든 함수 onPaymentSuccess를 호출합니다.
paymentModule.onEvent("paymentSuccess", onPaymentSuccess);

단계 13: 구성


우리는 두 가지 설정을 해야 한다.하나는 MQTT와 사물인터넷 노드로 MAM을 사용하여 사무 정보를 저장하는 것이다.다른 하나는 피드입니다. 지불 주소를 생성하고 사물인터넷 노드에 연결하는 데 사용되며 지불에만 사용됩니다.
4단계의 설정과 마찬가지로, 우리는adafruitio 사용자 이름과adafruitio 키를 변경하기만 하면 됩니다.이 구성은 here입니다.이 파일은 config로 저장해야 합니다.지방의json.
{
    "MQTT_CONFIG": {
        "ADAFRUIT_IO_URL": "io.adafruit.com",
        "ADAFRUIT_USERNAME": "",
        "ADAFRUIT_IO_KEY": "",
        "ADAFRUIT_IO_FEEDNAME": "pay-for-light.bulb-relay",
        "ADAFRUIT_IO_PORT": 8883
    },
    "node": {
        "provider": "https://nodes.devnet.iota.org:443",
        "depth": 3,
        "mwm": 9
    }
}
라는 다른 파일을 만듭니다.api 폴더의 env 파일입니다.다음 구성을 추가합니다.
seed=
iotaNodes=["https://nodes.comnet.thetangle.org:443"]
https://docs.iota.org/docs/getting-started/0.1/tutorials/create-a-seed으로 이동하여 명령 중 하나를 실행하여 피드를 생성합니다.그런 다음 피드 = 매개변수의 원형대로 피드를 붙여넣을 수 있습니다.

단계 14: 테스트


우리는 현재 다음 명령을 실행하여api 서버를 실행할 수 있습니다.cd api && npm run start이는api 서버를 시작합니다. 아래와 같습니다.

주의: npmrunstartdev를 실행하여 순환에 넣습니다.그것을 사용하지 마라.
일단api 서버가 시작되면, 당신은 지금 가게에 가서 당신의 사물인터넷 주소를 얻을 수 있습니다.이것은 위 그림에서 빨간색으로 강조 표시됩니다.
http://localhost:5000/iotapay/#/
일단 기계나 서버의 URL로 넘어가면 페이지가 이렇게 보입니다.

QR 코드 보기를 클릭하여 QR 코드를 표시합니다.QR코드를 스캔하여 지불할 수 있도록 사물인터넷 주소를 얻을 수 있습니다.

복제 주소를 클릭하여 사물인터넷 주소를 클립보드로 복사합니다.일단 우리가 사물인터넷 주소가 생기면, 우리는 지금 주어진 주소에 돈을 지불할 수 있다.
IOTA Comnet*Fauchet* 웹 사이트를 클릭하십시오.이 사이트는 지역 사회 테스트 인원에게 무료 영패를 제공한다.토큰은 시뮬레이션 지불 과정에 사용될 것이다.

사물인터넷 통신망 주소에 영패를 보내는 주소를 입력하고 금액을 지정합니다.

현재 우리는 3 IOTA 토큰을 보낼 것이다.일단 우리가 금액을 입력하면, 우리는 지금 클릭하여 발송할 수 있다.지불과 함께 선택할 수 있는 메시지를 추가할 수도 있습니다.

결제가 성공하면 거래가 전송되었습니다. 거래를 가리키는 링크가 있습니다.이것도 컨트롤러에 결제 성공으로 표시됩니다!주소 XXXX

위에 표시된 링크로 이동합니다. (여기에서mam 채널을 볼 수 있습니다.) 우리는 mam 브라우저에서 결제 정보와 이벤트를 볼 수 있습니다.아래 사진은 이 점을 보여 준다.



활동은 다음과 같습니다.
  • 사용자는
  • 등불에 3개의 영패를 지불하였다
  • 라이트
  • 불이 꺼지다
  • 그리고 불이 켜지고 3분 후에 꺼진다.

    한계성


    이 프로젝트의 한계는 다음과 같습니다.
  • 보안은 본 프로젝트의 MAM 채널에서 아직 구현되지 않았습니다.현재는 누구나 이 정보에 접근할 수 있다.개인 모드나 제한 모드를 사용하면 안전성을 강화할 수 있다.
  • 은 여러 건의 지불을 동시에 처리하는 메커니즘이 없다.한 번에 한 번만 지불을 해야만 정상적으로 일을 할 수 있다.예금 계좌가 하나 있고 금액을 확인하는 데 도움이 될 수 있습니다.또는
  • 을 지불하기 위해 줄을 서세요.
  • 등을 켤 수 있는 최장 시간은 59분이다.이 제한은 복구하기 쉬우므로 *npm* 모듈, 노드 스케줄링을 수정하여 더 많은 날짜와 시간을 허용해야 합니다.
  • 은 특정 거래를 얻을 수 없습니다.이것은 거래의 경쟁 목록을 보여 줍니다. 사용자는 그 중에서 특정 거래를 수동으로 검색해야 합니다.
  • 공구서류


    다음은 이 코드의 참고 자료입니다.
  • 결제 모듈 https://github.com/iota-pay/iota-payment-module
  • MAM(마스크 인증 메시지) https://github.com/iotaledger/mam.js
  • Adafruit IO https://github.com/adafruit/adafruit-io-node에 연결
  • 건축 관리 시스템 https://github.com/peterokwara/BuildingManagement
  • 에너지 사장은 케냐 전력 https://www.businessdailyafrica.com/analysis/columnists/Energy-boss-must-wake-up-Kenya-Power/4259356-5618224-cm7w40z/index.html을 깨워야 한다
  • 좋은 웹페이지 즐겨찾기