見出し画像

「AIしげちゃん」でNature Remoの環境センサーの値を取得

前回に引き続き破損前の「AIしげちゃん」にあった、Nature Remoの環境センサーの値を取得して、温湿度の値を答えるスキルを復活中。

ただ、センサーの値を答えるだけでは芸がないので、温湿度の値から不快指数を計算して、少し盛った会話ができるようにしているw

[SensorSkill.cs]

using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using Cysharp.Threading.Tasks;
using Newtonsoft.Json;
using ChatdollKit.Dialog;
using ChatdollKit.Dialog.Processor;

using System.Net.Http;

namespace ChatdollKit.Kazz
{
    public class SensorSkill : ChatGPTFunctionSkillBase
    {
        public string FunctionName = @"get_sensor";
        public string FunctionDescription = @"仕事部屋の環境センサーの値を取得します。環境センサーの種類は「Temperature」「Humidity」「Illuminance」です。";
        public string InstructionPrompt = @"以下は仕事部屋の環境センサーから取得した値です。あなた自身の言葉でユーザーに伝えてください。";
        private const string TOKEN_REMO
            = @"Nature Remo Cloud APIのアクセストークン";

        public override ChatGPTFunction GetFunctionSpec()
        {
            // Make function spec for ChatGPT Function Calling
            var func = new ChatGPTFunction(FunctionName, FunctionDescription);
            func.AddProperty("sensor_name", new Dictionary<string, object>() { { "type", "string" } });
            return func;
        }

        protected override async UniTask<FunctionResponse> ExecuteFunction(
            string argumentsJsonString, Request request, State state, User user, CancellationToken token)
        {
            // Parse arguments
            // var arguments = JsonConvert.DeserializeObject<Dictionary<string, string>>(argumentsJsonString);
            // var sensorName = arguments["sensor_name"];
            string message = string.Empty; ;

            try
            {
                string url = "https://api.nature.global/1/devices";
                var httpClient = new HttpClient();
                var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);
                httpRequest.Headers.Add("accept", "application/json");
                httpRequest.Headers.Add("Authorization", "Bearer " + TOKEN_REMO);
                var devicesResponse = await httpClient.SendAsync(httpRequest);

                var devicesjson = devicesResponse.Content.ReadAsStringAsync().Result;
                List<Device> devices = JsonConvert.DeserializeObject<List<Device>>(devicesjson);

                double te = devices[0].newest_events.te.val;
                double hu = devices[0].newest_events.hu.val;
                double il = devices[0].newest_events.il.val;
                double di = 0.81 * te + 0.01 * hu * (0.99 * te - 14.3) + 46.3;

                message = @"現在の温度は" + te.ToString() + @"度、湿度は" + hu + @"パーセント、照度は"
                    + il.ToString() + @"ルクス、不快指数は" + di.ToString("0.0") + @"で、";

                // 不快指数の算定
                if (di < 50)
                {
                    message += @"寒くてたまりません。";
                }
                else if (50 <= di && di < 55)
                {
                    message += @"寒いです。";
                }
                else if (55 <= di && di < 60)
                {
                    message += @"肌寒いです。";
                }
                else if (60 <= di && di < 65)
                {
                    message += @"特に何も感じません";
                }
                else if (65 <= di && di < 70)
                {
                    message += @"快適です。";
                }
                else if (70 <= di && di < 75)
                {
                    message += "暑くはありません。";
                }
                else if (75 <= di && di < 80)
                {
                    message += @"少し暑いです。";
                }
                else if (80 <= di && di < 85)
                {
                    message += @"暑くて汗が出ます。";
                }
                else if (85 <= di)
                {
                    message += @"暑くてたまりませんね。";
                }
            }
            catch
            {
                message = @"環境センサーの値を取得できませんでした。";
            }

            return new FunctionResponse(
                InstructionPrompt + $"\n\n{message}");
        }

        private class Device
        {
            //public string name { get; set; }
            //public string id { get; set; }
            //public DateTime created_at { get; set; }
            //public DateTime updated_at { get; set; }
            //public string mac_address { get; set; }
            //public string serial_number { get; set; }
            //public string firmware_version { get; set; }
            //public int temperature_offset { get; set; }
            //public int humidity_offset { get; set; }
            //public List<User> users { get; set; }
            public NewestEvents newest_events { get; set; }
        }

        //private class User
        //{
        //    public string id { get; set; }
        //    public string nickname { get; set; }
        //    public bool superuser { get; set; }
        //}

        private class NewestEvents
        {
            public Te te { get; set; }
            public Hu hu { get; set; }
            public Il il { get; set; }
        }

        private class Te
        {
            public double val { get; set; }
            //public DateTime created_at { get; set; }
        }

        private class Hu
        {
            public double val { get; set; }
            //public DateTime created_at { get; set; }
        }

        private class Il
        {
            public double val { get; set; }
            //public DateTime created_at { get; set; }
        }
    }
}

GPTのFunction Callingでセンサーの種類を返すようにしているけど、温度、湿度、照度の値をすべて答えるようにしているので、実際には使ってない。

作成したスキルを ChatdollKitVRMにアタッチしておけば、ChatGPTRouterが起動時にFunction Callingの関数として登録してくれる。ありがたいね。

いいなと思ったら応援しよう!