/**
 * Copyright © 2017-2018 Shanghai Lebai Robotic Co., Ltd. All rights reserved.
 *
 * FileName: robot_controller.proto
 *
 * Author: Yonnie Lu
 * Email: zhangyong.lu@lebai.ltd
 * Date: 2019-10-31 10:20:01
 * Description:
 * History:
 *   <Author>      <Time>    <version>    <desc>
 *   YonnieLu      2019-10-31 10:20:01   1.0          Create
 *
 * compile methods:
 * 1. c++
 * protoc --grpc_out=./ --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` *.proto
 * protoc --cpp_out=. *.proto
 *
 * 2. golang
 * protoc *.proto --go_out=plugins=grpc:../
 *
 * 3. python
 */
syntax = "proto3";

import "google/protobuf/empty.proto";
import "messages.proto";

package robotc;

service RobotPrivateController {
  // 初始化配置
  rpc Init(Configuration) returns (Response);
  // 获取机器人基础信息
  rpc GetRobotInfo(google.protobuf.Empty) returns (RobotInfo);
  // 设置机器人安装方向
  rpc SetInstallDirection(InstallDirection) returns (Response);
  // 设置碰撞检测
  rpc SetCollisionDetector(CollisionDetector) returns (Response);
  // 设置关节配置
  rpc SetJointConfig(JointConfigs) returns (Response);
  // 设置笛卡尔空间的配置
  rpc SetCartesianConfig(CartesianConfig) returns (Response);
  // 开启DDS
  rpc EnableDDS(TrueOrFalse) returns (Response);
  // 设置碰撞检测力矩差阈值
  rpc SetCollisionTorqueDiff(CollisionTorqueDiff) returns(Response);
  // 注册通知事件
  rpc RegisterNotification(google.protobuf.Empty) returns (stream Notification);
  rpc RobotDriverInfo(google.protobuf.Empty) returns (DriverInfo);
  // 机器人OTA单个设备更新接口
  rpc RobotOTA(OTAData) returns (stream OTAResult);
  // 通知灯板、法兰、关节切换分区
  rpc SwitchOtaPartition(OTACmd) returns (Response);
  // 机器人OTA批量更新接口
  rpc RobotOTABatch(OTADatas) returns (stream OTAResults);
  // 重置
  rpc Reset(google.protobuf.Empty) returns(Response);
  // 以给定角度置零
  rpc InitZero(Zero) returns (Response);
  // 以零位置零
  rpc SetZero(google.protobuf.Empty) returns (Response);
  // 获取机器人电压V
  rpc GetVoltage(google.protobuf.Empty) returns (CurrentVoltage);
  // 设置单关节伺服参数
  rpc SetServoParam(JointServoParam) returns (JointServoParams);
  // 获取当前所有关节伺服参数
  rpc GetServoParams(google.protobuf.Empty) returns (JointServoParams);
  // 调试设置
  rpc SetDebugParams(DebugParams) returns (DebugParams);
  // 更改DH参数（三轴平行6参数）
  rpc FixDHParams(FixDHRequest) returns (FixDHResult);
  // 设置LED样式
  rpc SetLEDStyle(LEDStyle) returns (LEDStyles);
  // 获取LED样式
  rpc GetLEDStyles(google.protobuf.Empty) returns (LEDStyles);
  // 注册命令状态事件
  rpc RegisterLuaEvent(google.protobuf.Empty) returns (stream LuaEvent);
  // 当推送 ALERT/CONFIRM/INPUT/SELECT，用户在前端确定后调用该接口
  rpc ConfirmCallback(ConfirmInput) returns (Response);
  // 获取 Lua 上次执行到的机器人位置
  rpc GetLastPose(google.protobuf.Empty) returns (PoseRes);
  //配置Modbus外部IO设备
  rpc SetModbusExternalIO(ModbusExternalIOs) returns (Response);
  // 修改按钮配置
  rpc SetButtonConfig(ButtonConfig) returns (Response);
  // 设置绑定设备开关, true: 不限制设备绑定； false：限制设备绑定逻辑
  rpc SetBreakACup(TrueOrFalse) returns (Response);
  // PVAT数据记录接口，用户记录pvat数据
  rpc RecordPVAT(RecordPVATRequest) returns (stream RecordPVATResponse);
  rpc StopRecordPVAT(google.protobuf.Empty) returns (Response);
  // 语音升级
  rpc UpgradeVoiceFile(VoiceFile) returns (stream VoiceResult);//yvoice
  // 获取当前 DH 参数
  rpc GetDHParams(DHRequest) returns (DHParams);
  // 设置 DH 参数并返回设置后的结果
  rpc SetDHParams(DHParams) returns (DHParams);
  // 伺服控制参数
  rpc WriteExtraServoParam(ExtraServoParam) returns (ExtraServoParam);
  rpc ReadExtraServoParam(ExtraServoParam) returns (ExtraServoParam);
  rpc WriteExtraServoParams(ExtraServoParam) returns (ExtraServoParams);
  rpc ReadExtraServoParams(google.protobuf.Empty) returns (ExtraServoParams);
  rpc ResetExtraServoParams(google.protobuf.Empty) returns (ExtraServoParams);
  // “主动消回差”参数
  rpc WriteJointBacklash(JointBacklash) returns (JointBacklash);
  rpc ReadJointBacklash(JointBacklash) returns (JointBacklash);
  rpc WriteJointBacklashes(JointBacklash) returns (JointBacklashes);
  rpc ReadJointBacklashes(google.protobuf.Empty) returns (JointBacklashes);
  rpc ResetJointBacklashes(google.protobuf.Empty) returns (JointBacklashes);
  // 启用主动消回差
  rpc WriteEnableJointBacklashes(EnableJointBacklash) returns (EnableJointBacklashes);
  rpc ReadEnableJointBacklashes(google.protobuf.Empty) returns (EnableJointBacklashes);
  rpc ResetEnableJointBacklashes(google.protobuf.Empty) returns (EnableJointBacklashes);
  // 关节回差参数
  rpc WriteJointBacklashParam(JointBacklashParam) returns (JointBacklashParam);
  rpc ReadJointBacklashParam(JointBacklashParam) returns (JointBacklashParam);
  rpc WriteJointBacklashParams(JointBacklashParam) returns (JointBacklashParams);
  rpc ReadJointBacklashParams(google.protobuf.Empty) returns (JointBacklashParams);
  rpc ResetJointBacklashParams(google.protobuf.Empty) returns (JointBacklashParams);
  // 关节限位检测
  rpc EnableJointLimit(TrueOrFalse) returns (Response);
  rpc SwitchSimulate(TrueOrFalse) returns (Response);
  // 连接/断开 MODBUS 设备
  rpc ConnectExternalIO(ExternalIOState) returns (Response);
}

message EnableJointBacklash {
  int32 joint = 1;
  bool enable = 2;
}

message EnableJointBacklashes {
  repeated EnableJointBacklash joints = 1;
}

message ExtraServoParam {
  int32 joint = 1; // 当 Read、Enable/Disable 时仅该值生效, 0 代表关节 1

  double acc_position_kp = 2;
  double acc_speed_kp = 3;
  double acc_speed_it = 4;
  double uni_position_kp = 5;
  double uni_speed_kp = 6;
  double uni_speed_it = 7;
  double dec_position_kp = 8;
  double dec_speed_kp = 9;
  double dec_speed_it = 10;
}

message ExtraServoParams {
  repeated ExtraServoParam joints = 1;
}

message JointBacklash {
  int32 joint = 1;

  uint32 k = 2;
  double iq = 3;
  double iq_final = 4;
  uint32 iq_count = 5;
}

message JointBacklashes {
  repeated JointBacklash joints = 1;
}

message JointBacklashParam {
  int32 joint = 1;

  int32 encoder_data_offset = 2;
  uint32 on = 3;
  uint32 over = 4;
  uint32 leave = 5;
  uint32 max = 6;
}

message JointBacklashParams {
  repeated JointBacklashParam joints = 1;
}

message VoiceFile {//yvoice
  int32 id = 1;
  string file = 2;
  string md5 = 3;
}

message VoiceResult {//yvoice
  int32 id = 1;
  int32 step = 2;// 0: not begin, 1: downloading, 2: flashing, 3: done, 4:fail
  int32 stepProgress = 3;// 0-100, currently only downloading step has progress, other steps need show pending progress
}

//0: all joints    1-7:joint1-7   8:flan  9:claw  10:lamp
enum BootloaderId {
  ALL_JOINTS = 0;
  JOINT_1 = 1;
  JOINT_2 = 2;
  JOINT_3 = 3;
  JOINT_4 = 4;
  JOINT_5 = 5;
  JOINT_6 = 6;
  JOINT_7 = 7;
  FLANGE = 8;
  CLAW = 9;
  LAMP = 10;
  COMBOARD = 14;
}

enum BootPartition {
  A = 0;
  B = 1;
  C = 2;
  PART_UNKNOWN = 3;
}

// Message definition
message TrueOrFalse {
  bool val = 1;
}

message InstallDirection {
  int32 direction = 1; // 安装方式: 0: up; 1: down; 2: side, default: UP
}

message JointConfig {
  double maxAngle = 1;
  double minAngle = 2;
  double maxV = 3;  // 用户端设定的全局速度拆分到每个关节的maxV上
  double maxAcc = 4;
}

message JointConfigs {
  repeated JointConfig configs = 1;
}

message CartesianConfig {
  double maxV = 1;
  double maxAcc = 2;
}

message SafetyPlat { // 安全平面，点为平面四个角的顶点，非示教的三个点
  repeated Coordinate points = 1;
}

message SafetyPlats {
  repeated SafetyPlat plats = 1; // default: empty
}

message CollisionTorqueDiff { // 每个关节碰撞检测的扭矩差值
  repeated double diffs = 1;
}

message CollisionDetector {
  bool enable = 1;       // 是否启用碰撞检测, default: false
  int32 action = 2;    // 碰撞检测后动作, 0: estop, 1: pause default: ESTOP
  int32 pauseTime = 3;           // 碰撞检测暂停时间, default: 0
  int32 sensitivity = 4;         // 碰撞检测灵敏度, , default: 50
}

message LEDStyle {
  int32 mode = 3;
  int32 speed = 4;
  repeated int32 color = 5;
  int32 voice = 1;
  int32 volume = 2;
  int32 robotMode = 6; // robot-mode
}

message LEDStyles {
  repeated LEDStyle styles = 16; // 机器人状态对应的LED样式，下标为robot-mode
}

message ButtonConfig {
  bool btn_flan_1 = 1; // 
  bool btn_flan_2 = 2;
  bool btn_shoulder_0 = 3;
}

message Configuration {
  InstallDirection installDirection = 1;
  CollisionDetector collisionDetector = 2;
  JointConfigs jointConfigs = 3;  // 0-6 关节配置
  SafetyPlats safetyPlats = 4;    // 安全平面列表
  PR tcp = 5;                             // tcp配置
  Payload payload = 6;                    // 负载
  bool enableDDS = 7;                    // 是否开启内部数据调试服务（Data Debug Service),默认关闭
  CollisionTorqueDiff collisionTorqueDiff = 8;

  int32 robotDIOInNum = 9;
  int32 robotDIOOutNum = 10;
  repeated AIO robotAIOInConfig = 11;
  repeated AIO robotAIOOutConfig = 12;
  int32 tcpDIOInNum = 13;
  int32 tcpDIOOutNum = 14;
  repeated double zeros = 15; // 关节归零角度 (弃用)
  repeated LEDStyle styles = 16; // 机器人状态对应的LED样式
  bool break_a_cup = 17; // true: 不校验启动验证绑定设备hash逻辑; false: 默认值，校验 
  ButtonConfig button_config = 18;
  CartesianConfig cartesianConfig = 19;
  int32 extra_robotDIOInNum = 20;
  int32 extra_robotDIOOutNum = 21;
  repeated AIO extra_robotAIOInConfig = 22;
  repeated AIO extra_robotAIOOutConfig = 23;
}


message Zero {
  repeated double zeros = 1;
}

message Notice {
  // 通知类型
  enum NoticeType {
    NOTICE_STATE = 0;  // 机器人状态变更；机器人状态和急停状态位等
    NOTICE_ERROR = 1;  // 错误：错误类型
    NOTICE_BUTTON = 2; // 按钮事件；
  }

  // 按钮类型的nId定义
  enum NoticeId {
    NOTICE_ID_STATE_ROBOT_STATE = 0;    // 机器人状态
    NOTICE_ID_STATE_E_STOP = 1;         // 机器人状态
    NOTICE_ID_STATE_DATA_UPDATE = 2;    // 机器人数据有更新
    NOTICE_ID_ERROR = 3;                // 机器人错误
    NOTICE_ID_BUTTON_SHOULDER = 4;      // 肩部按钮
    NOTICE_ID_BUTTON_FLANGE_1 = 5;      // 末端按钮1
    NOTICE_ID_BUTTON_FLANGE_2 = 6;      // 末端按钮1
  }

  NoticeType type = 1; // 通知类型
  /**
   * type = 1 按钮事件
   *    value: 按钮模式：1: 按钮空闲；2：长按；3：单击；4: 双击
   */
  NoticeId id = 2;
  int32 value = 3; // when there ERROR, value represent the LEVEL
  int32 code = 4;
  // some fucking boring and important data need return back to front end
  repeated double lol = 5;
  int32 count = 6; // 肩部按钮按下时，按该按钮的次数
}

message Notification {
  repeated Notice items = 1;
}

message Driver {
  // 驱动器基本信息
  Hardware hardware = 1;
  // 当前运行分区情况
  BootPartition curPartition = 2;
}

message DriverInfo {
  Driver flange = 1;
  Driver led = 2;
  repeated Driver joints = 3;
  Driver comboard = 4;
}

message OTAFile {
  string file = 1; // 文件完整路径
  string md5 = 2; // 文件原始md5，前端计算
  // version string: XX.YY.ZZ.20200608
  string version = 3;
}

message OTACmd {
  BootloaderId bootloaderId = 1;
  // 0: B分区；1: C分区
  BootPartition targetPartition = 2;
}

message OTAData {
  OTACmd cmd = 1;
  OTAFile file = 2;
}

message OTAJoints {
  repeated OTACmd cmds = 1;
  OTAFile file = 2;
}

message OTADatas {
  // 所有关节更新描述
  OTAJoints joints = 1;
  // 非关节更新描述： 灯板，法兰
  repeated OTAData notJoints = 2;
}

message OTAResult {
  BootloaderId bootloaderId = 1;
  int32 step = 2; // 0: not begin, 1: downloading, 2: flashing, 3: done, 4:fail
  int32 stepProgress = 3;  // 0-100, currently only downloading step has progress, other steps need show pending progress
  string version = 4;
  BootPartition partition = 5;
}

message OTAResults {
  repeated OTAResult results = 1;
}

message CurrentVoltage {
  double power = 1; // 电源电压V/电流mA
  double flan = 2; // 法兰电压/电流
  repeated double joint = 3; // 关节电压/电流
  double io_power = 4; // IO板
}

message JointServoParam {
  uint32 index = 1; // 0代表关节一
  double position_kp = 2;
  double speed_kp = 3;
  double speed_it = 4;
  double torque_cmd_filter = 5;
}

message JointServoParams {
  repeated JointServoParam joints = 1;
}

message DebugParams {
  repeated double d = 1;
}

message FixDHRequest {
  repeated double delta_theta = 1;
  bool plus_theta = 2; // true则走到theta位再置零，false则走到-theta位再置零
  repeated double delta_l = 3;
  bool plus_l = 4; // true则加，false则减
}

message DHRequest {
  bool get_theoretical = 1; // 是否获取理论dh参数
}

message DHt {
  double d = 1;
  double a = 2;
  double alpha = 3;
  double theta = 4;
}

message DHParams {
  repeated DHt params = 1;
}

message FixDHResult {
  repeated DHt origin = 1;
  repeated DHt before = 2;
  repeated DHt after = 3;
}

message Option {
  string value = 1;
  string label = 2;
}

message LuaEvent {
  enum Type {
    ECHO = 0;
    LUA = 1;
    SIGNAL = 2;
    LOOP = 3;
    ALERT = 4;
    CONFIRM = 5;
    INPUT = 6;
    SELECT = 7;
  }
  enum CmdState {
    INIT = 0;
    RUNNING = 1;
    SUCCESS = 2;
    FAILED = 3;
  }

  Type type = 1;
  // type: ECHO
  int32 cmd_id = 2;
  CmdState cmd_state = 3;
  // echo_key
  // 当type=Lua时，该字段表示错误消息;
  // 当type=LOOP 时表示loopid
  // 当type=ALERT/CONFIRM/INPUT/SELECT时，该字段表示提示语
  string echo_key = 4;
  // index
  // 当type=LOOP时，表示进行到了第几个循环
  // 当type=LUA时，表示对应的任务ID
  int32 index = 8;
  // type: LUA
  LuaState lua_state = 5;
  // type: SIGNAL
  int32 signal_id = 6;
  double signal_value = 7;
  // type: SELECT
  repeated Option options = 9;
}

message ConfirmInput {
  string input = 1; // CONFIRM时为"true"|"false", INPUT为用户输入字符串, SELECT为用户选择的value
}

message PoseRes {
  PR cart = 1; // 笛卡尔位置
  JPose joint = 2; // 关节位置
}

message ModbusDio {
  int32 pin = 1;
  //对应modbus内部地址
  int32 addr = 2;
}

message ModbusDioGroup {
  repeated ModbusDio pins = 1;
  int32 addr = 2;
}

message ModbusAio {
  int32 pin = 1;
  // 0: 电压型 1: 电流型
  int32 mode = 2;
  //对应Modbus内部地址 
  // 一个addr占用2bytes=16bits
  int32 addr = 3;
}

message AIORange {
  double min = 1;
  double max = 2;
}

message Range {
  AIORange V = 1;
  AIORange A = 2;
}

message ModbusAioGroup {
  repeated ModbusAio pins = 1;
  // modbus base address
  int32 addr = 2;
  //大小端
  int32 isLsb = 3;
  Range range = 4;
  // number of 16 bit words for one pin
  int32 size = 5;
}

message ModbusExternalIOMapping {
  // 所有数字量的输入值
  ModbusDioGroup di = 1;
  // 所有数字量的输出值
  ModbusDioGroup do = 2;
  // 所有模拟量输入值
  ModbusAioGroup ai = 3;
  // 所有模拟量输出值
  ModbusAioGroup ao = 4;
}

message ExternalIOState {
  int32 id = 1;
  bool enable = 2; // true 连接 false 断开
}

message ModbusExternalIO {
  int32 id = 1;
  string ip = 2;
  int32 port = 3;
  int32 timeout = 4;
  int32 slaveId = 5;
  int32 cmdHoldTime = 6;
  int32 version = 7;
  ModbusExternalIOMapping ioMap = 8;
}

message ModbusExternalIOs {
  repeated ModbusExternalIO ios= 1;
}

message RecordPVATRequest {
  enum PVATType {
    PT = 0;
    PVT = 1;
    PVAT = 2;
  }

  message VZeroGap {
    double threshold = 1; // v zero gap threshold should be > 0 and < 0.01
    bool remove_gap = 2; // whether to remove zero gap during teaching
  }

  PVATType type = 1;
  double duration = 2; // duration in microseconds
  VZeroGap vZeroGap = 3;
  bool use_duration_ts = 4;
  bool save_file = 5;
}

message RecordPVATResponse {
  repeated double p = 1;
  repeated double v = 2;
  repeated double acc = 3;
  double t = 4;
  bool end = 5; // is pvat end
  string f = 6; // data save file path, local
}