# Cloud-to-cloud services

# 1. Operating environment requirements

  • x86_64 Operating environment
  • glibc 2.28 Or more
  • libcurl 7.84.0 Or more

# 2. Server-side message reception and push

To the specified Openid After initiating the call, if the call is successful, the WeChat open platform will follow the standard Message Push Method pushes a message to the developer background. Developers in accordance withMessage PushInstructions to configure the callback address, the message encryption method must be selectedSecurity mode。

It should be noted that the vendor role may need to service multiple Mini Programs, which can be used <a href=https://developers.weixin.qq.com/doc/oplatform /Third-party_Platforms/2.0/operation/thirdparty/config.html>Third-party platform development。

The push message is roughly as follows:

{"ToUserName":"gh_27632a25xxx,"Encrypt":"xxxx"} 

// Encrypt The contents after decryption, refer to the field explaination.

After the developer background receives the message notification, it is necessary to reply to the request in time, otherwise it may trigger the resend of WeChat background. The correct reply format is as follows:

{"errcode":0,"errmsg":"ok"} 

Errcode for 0 Successful response, openid WeChat is the ring. if Errcode For non 0 Value, the WeChat side will not ring, the call is cancelled.

Field Dxplaination:

parameter Data type Introductions
Action String The event type of the platform accessing the developer's backend is fixed to join_voip_room
RoomId String Room id for this call
SessionKey String Of this call. sessionkey
ServerToken String The server credentials for this call
Payload String A custom payload passed in by a third party when a call is initiated
ModelId String Models
Sn String Sn

Examples of content:

{
"ToUserName":"gh_12345678",
"FromUserName":"openid",
"CreateTime":1709621375,
"MsgType":"event",
"Event":"iot_voip_notify",
"Action":"join_voip_room",
"Payload":"hello",
"RoomId":"wxf830863afde621ebWmpfVoip112343434123434",
"SessionKey":"COrwxeDmrJQuEOrwxeDmrJQuGhhrpMKQHttT1pG4eldlqIhi/L2qFpMQkn0iGCpUjLhxpYobRqjPK4DHWCHgRBi123412341234",
"ServerToken":"xyrOs /pwIHEZf3MFNjbhRHkL5XOmGDtW2nkor6EcmRLtHcoI6mP123412341234==",
"ModelId":"fJ4exxxx," 
"Sn":"1234"
}

# 3. Service-side VOIP SDK

Service-side sdk yesSingleton pattern, i.e. sdk Only one audio - video call can be processed at the same time. As the developer's server often requires simultaneous processing of multiple calls, so the cloud server backend access to the server sdk You need to create a new process every time there is a new request and call the server in the process. sdk Interface to complete the audio and video calls.

Get the call through the message push server_Token and payload After that, you can use sdk Establish a call.

Service-side sdk For a data file path, call the wx_init Function to complete the initialization work (no Mini Program required appid and models. And then by Join Interface Join VoIP At the same time receiving the audio and video data flow of the device through the server. sdk The relevant interface of the device fills in the data or receives the data, and the audio and video stream communication between the device and the WeChat user can be completed.

# 4. Interface Dxplaination

The specific interface is as follows, please refer to the use of sdk In the bag example Under the directory Demo Code.

wmpf.h

// Copyright (c) 2023, Tencent Inc.
// All rights reserved.
#pragma once

#include "wmpf/macros.h 
#include "wmpf/module.h"
#include "wmpf/operation.h"
#include "wmpf/types.h"

WX_BEGIN_DECLS

typedef enum wx_wxa_flavor {
  WX_WXA_FLAVOR_RELEASE = 0,  // Mini Program official
  WX_WXA_FLAVOR_DEBUG = 1,    // Mini Program Development Edition
  WX_WXA_FLAVOR_DEMO = 2,     // Mini Program experience version
} wx_wxa_flavor_t

#Define WX_INIT_CONFIG_TAG 0x00001

/**
 * @brief WMPF Initialize structural body
 *
 * It is strongly recommended that you use this structure before memset  Zero, Avoid forgetting an item's settings.
 */
typedef struct wx_init_config {
  wx_struct_t common

  /**
   * @brief WMPF Log folder
   *
   * For storage WMPF Log file.
   *
   * If this is filled NULL, WMPF The log will not be output.
   */
  const char* log_dir

  /**
   * @brief WMPF Data file folder
   *
   * For storage WMPF Data files.
   *
   * WMPF Data files will store important, one-time registrations related to the device.
   * Cannot restore after deletion. If you need to empty device data, then you need a backup WMPF The data file of the.
   */
  const char* Data_dir

  /**
   * @brief product ID.
   *
   * This fill 0.
   */
  int product_id

  /**
   * @brief HostAppID
   *
   * This fill NULL.
   */
  const char* host_appid

  /**
   * @brief equipment ID (SN)
   *
   * Unique identifier for the device (Unique Serial Number), This item needs to be defined by the manufacturer.
   */
  const char* device_id

  /**
   * @brief Device signature
   *
   * This fill NULL.
   */
  const char* device_signature

  /**
   * @brief Device Signature Version
   *
   * This fill 0.
   */
  int device_signature_version

  /**
   * @brief Model ID
   *
   * Model ID Is called the Mini Program device interface important credentials.
   * When the device access from the [Mini Program management background] application obtained Model ID.
   *
   * @see
   * https://developers.weixin.qq.com/miniprogram/dev/framework/device/device-access.html
   * https://developers.weixin.qq.com/miniprogram/dev/framework/device/device-message.html
   */
  const char* model_id

  /**
   * @brief Mini Program AppID
   *
   * Mini Program AppID Is the unique identifier of the Mini Program, in VoIP This is required for the scenario.
   * in VoIP After initiating the call, The phone of the dialed WeChat user will pull up the mini program designated here for the call.
   */
  const char* wxa_appid

  /**
   * @brief Mini Program version
   *
   * for VoIP Scene: To run WeChat in the official version of the mini program VoIP,
   * Need to submit the device to WeChat after approval to get the relevant permissions. So during the commissioning,
   * You need to use the Mini Program Developer Edition/Experience Edition Test VoIP Availability of features.
   *
   * To be set as Development or Experience, Please consult your Mini Programs development colleagues.
   *
   * Attention, If the device development colleagues need to test the Mini Program development version VoIP Function,
   * Device developers must first obtain the Mini Programs developer permissions.
   * And promptly scan the real machine of the mini program developer's WeChat developer tool to debug the qr code.
   * In advance in the local WeChat client open a development version of the Mini Program, Otherwise, the WeChat client will receive VoIP
   * When the call is strong, There will be a lack of Mini Program development version of the code package, Causes the Mini Program to fail to start.
   */
  wx_wxa_flavor_t wxa_flavor

  /**
   * @brief RPMB Device path
   *
   * If the device has RPMB and Key In a writable state, Should be adopted RPMB Mode initialization SDK.
   * And passed in RPMB Device path (Generally for /dev/mmXXXXX)
   */
  const char* rpmb_device

  /**
   * @brief Does it only support H265
   *
   * If the device only supports H265, you can set this field to true.
   * 
   * If not set, WeChat voip Background will be adaptive, developers can also send H265 Stream, but cannot decide what type of stream the phone is coming over.
   * If the setting True, then both sending and receiving are H265。
   */
  bool h265_only

  /**
   * @brief SDK Whether the receive Mini Program push stream is 4:3 Of the stream.
   *
   * true:  SDK Aspect ratio of the received stream 4:3 --- 320x240 480x352 640x480 1280x720 1920x1080
   * false: SDK Aspect ratio of the received stream 3:4 --- 240x320 352x480 480x640 720x1080 1080x1920
   */
  bool video_landscape

  /**
   * @brief Subscribe SDK Resolution expected to be received
   *
   * Developers can use this configuration to subscribe to a resolution of the long boundary value.
   * This feature is primarily aimed at devices that do not wish to receive variable resolution video streams. If this feature is not used, the SDK The received video stream will have different resolutions in different network environments.
   * This feature needs to be submitted to WeChat at the same time Appid, which takes effect after the subscription mechanism is opened.
   * This configuration currently supports only the following two values:
   *   320: video_landscape = true Received at the time was 320x240,video_landscape = Fale Received at the time was 240x320
   *   640: Not support video_landscape = true Mode, video_landscape = Fale Received at the time was 480x640
   */
  int subscribe_video_length
} wx_init_config_t

/**
 * @brief to initialize WMPF
 *
 * In the execution of arbitrary WMPF Need to call before calling wx_init() to initialize WMPF.
 * Function to provide basic information about the device, up and running WMPF.
 *
 * This function is asynchronous, There are network requests, Make sure the network is clear when calling this function.
 *
 * @param  config (nonnull ) The initial parameters, Contains the initial information about the device
 * @param  get_Module (nonnull ) WMPF Get the callback function of the interface provided by the manufacturer, See Implementation Methods
 * wx_get_Module_t The documentation of the
 * @return Run successfully
 *   - WXERROR_INVALID_ARGUMENT: The input parameters are not legal, or the product ID, equipment
 * ID, device signature mismatch
 *   - WXERROR_TIMEOUT: to exceed the time limit
 *   - WXERROR_RESOURCE_EXHAUSTED: Network not connected or local disk write failed
 *   - WXERROR_FAILED_PRECONDITION: Equipment not passed adddevice Registration, or wx_init
 * Has been called, The current system time is incorrect.
 *   - WXERROR_INTERNAL: Other mistakes
 */
WX_API wx_operation_t wx_init(const wx_init_config_t* config,
                              wx_get_Module_t get_Module)

/**
 * @brief stop WMPF
 *
 * Before calling this function, You need to make sure that the created wx_operation, wx_voip_session Such objects have been
 * destroy, otherwise SDK It will collapse.
 *
 * @return Operation is successful
 */
WX_API wx_error_t wx_stop()

WX_END_DECLS

cloudvoip_server.h

#pragma once

#include "wmpf/macros.h 
#include "wmpf/operation.h"
#include "wmpf/types.h"

WX_BEGIN_DECLS

typedef struct wx_cloudvoip_session* wx_cloudvoip_session_t

typedef enum wx_cloudvoip_session_type {
  WX_CLOUDVOIP_SESSION_VIDEO = 0,  // Audio and video call
  WX_CLOUDVOIP_SESSION_AUDIO = 1,  // Audio-only call
} wx_cloudvoip_session_type_t

typedef enum wx_cloudvoip_session_status {
  WX_CLOUDVOIP_SESSION_IDLE = 0,     // Initial state
  WX_CLOUDVOIP_SESSION_CALLING = 1,  // In the middle of the phone
  WX_CLOUDVOIP_SESSION_TALKING = 2,  // On the phone (The WeChat user who was dialed answered the call)
  WX_CLOUDVOIP_SESSION_REJECTED = 3,  // The dialed WeChat user refused to answer the call
  WX_CLOUDVOIP_SESSION_CANCELED = 4,  // During the call, The device canceled the call.
  WX_CLOUDVOIP_SESSION_HANGUP_BY_CALLER = 5,  // The device hung up during the call.
  WX_CLOUDVOIP_SESSION_HANGUP_BY_CALLEE =
      6,  // The WeChat user who was dialed during the call hung up
  WX_CLOUDVOIP_SESSION_ABORTED = 7,  // Abnormal occurrence
  WX_CLOUDVOIP_SESSION_BUSY = 8,  // The WeChat user who is dialed is busy.
  WX_CLOUDVOIP_SESSION_TIMEOUT = 9,  // Timeout not answered
} wx_cloudvoip_session_status_t

typedef enum wx_cloudvoip_hangup_reason {
  WX_CLOUDVOIP_HANGUP_REASON_UNKNOWN = 0,
  WX_CLOUDVOIP_HANGUP_REASON_MANUAL = 1,  // User manual hang up/cancel

  // Reason for calling hang up
  WX_CLOUDVOIP_HANGUP_REASON_SYSTEM = 6,  // Hang up by the system phone
  WX_CLOUDVOIP_HANGUP_REASON_APP = 7,     // Hang up by other applications
  WX_CLOUDVOIP_HANGUP_REASON_DEVICE = 8,  // Acquisition and playback device startup failure

  WX_CLOUDVOIP_HANGUP_REASON_TIMEOUT = 10, // Timeout hang up
  WX_CLOUDVOIP_HANGUP_REASON_REJECT = 11, // Deny a call, which means hang up without entering the call
} wx_cloudvoip_hangup_reason_t

#Define WX_CLOUDVOIP_SESSION_LISTENER_TAG 0xF00001

typedef struct wx_cloudvoip_session_listener {
  wx_struct_t common

  /**
   * @brief current VoIP Call Status Change
   *
   */
  void (*status)(wx_cloudvoip_session_t session,
                 void* user_data,
                 wx_cloudvoip_session_status_t)

} wx_cloudvoip_session_listener_t

/**
 * @brief Service-side join VoIP Room and create VoIP Session object
 *
 * Need to note:
 * This interface is used for device side SDK Initiated call to join.
 * Service-side SDK Is singleton mode, you cannot create two or more simultaneous within a single process
 * wx_cloudvoip_session Examples. So you need to use the multi-process mode to call the server SDK.
 * It may also be involved here. IPC Requires vendor clouds to implement themselves.
 *
 * initiate VoIP Call Process:
 * 1. Device end SDK call call Method to initiate a call
 * 2. WeChat background request manufacturer cloud background, notify cloud background has a new VoIP The session has been initiated
 * 3. Cloud backend call server SDK of wx_cloudvoip_session_Join Method Addition  VoIP conversation
 * 4. Cloud Backstage via audio_module, Camera_Module Streaming audio and video to the server SDK
 * 5. Service-side SDK The received audio and video stream is sent to the WeChat background, and then sent to the user's mobile phone WeChat
 *
 * @param  listener Session state callback
 * @param  user_Data Callback user data
 * @param  wxa_appid Mini Program AppId
 * @param  device_id equipment SN
 * @param  model_id Model ID
 * @param  server_Token WeChat backstage to the cloud backstage notification VoIP The value with which the session originated
 * @param  payload Device side call wx_cloudvoip_client_call Function passed in payload
 * @param  session_out VoIP Session Results
 * @return
 *   - WXERROR_INVALID_ARGUMENT: Parameter error
 *   - WXERROR_FAILED_PRECONDITION: wx_init Not called or not completed.
 */
WX_API wx_operation_t
wx_cloudvoip_session_Join(wx_cloudvoip_session_type_t,
                          const struct wx_cloudvoip_session_listener* listener,
                          void* user_data,
                          const char* wxa_appid, 
                          const char* device_id,
                          const char* model_id,
                          const char* server_token,
                          const char* payload,
                          wx_cloudvoip_session_t* session_out)

/**
 * @brief Hang up after successful call VoIP call
 *
 * Due to the equipment end SDK Does not provide hang up method, cloud to cloud scenario, by the manufacturer cloud background call the server side SDK
 * The hang up function hangs up VoIP Call.
 *
 * @param  session To hang up. VoIP conversation
 * @param  reason to hang up VoIP The reason for the call
 * @return Operation is successful
 */
WX_API wx_operation_t
wx_cloudvoip_session_hangup(wx_cloudvoip_session_t session,
                            wx_cloudvoip_hangup_reason_t reason)

/**
 * @brief As the recipient(Mini Program call device)to hang up VoIP, This interface is not recommended if it is a device call Mini Program.
 *
 * Mini Program call device scene, device end hang up voip Interface. If session Has been created, you need to use the wx_cloudvoip_session_hangup to hang up
 *
 * @param  wxa_appid Mini Program AppId
 * @param  device_id equipment SN
 * @param  model_id Model ID
 * @param  server_Token WeChat backstage to the cloud backstage notification VoIP The value with which the session originated
 * @param  payload Device side call wx_cloudvoip_client_Join Function passed in payload
 * @return Operation is successful
 */
WX_API wx_operation_t wx_cloudvoip_listener_hangup(
    const char* wxa_appid, 
    const char* device_id,
    const char* model_id,
    const char* server_token,
    const char* payload,
    wx_cloudvoip_hangup_reason_t reason)

/**
 * @brief Destroy VoIP Session object
 *
 * @param  session
 * @return WX_API
 */
WX_API void wx_cloudvoip_session_destroy(wx_cloudvoip_session_t session)

/**
 * @brief Get the current session of roomid
 *
 *  roomid: voip To the room where the call was made.
 * 
 * @param  session
 * @return roomid Character string or "".
 */
WX_API const char* wx_cloudvoip_session_get_roomid(wx_cloudvoip_session_t session)

/**
 * @brief Set the bandwidth of the end (WeChat) to force the flow control, after setting the upstream bit rate of the end will fluctuate around this value
 * 
 * @param  session
 * @param  bandwidth Bit rate, in units of kbps. such as 100, then the bit rate is 100 kbps
 * @return
 *  WXERROR_OK: Operation successfully
 *  WXERROR_FAILED_PRECONDITION: session Does not meet the conditions
 *  WXERROR_INTERNAL: Internal error
 */
WX_API wx_error_t wx_cloudvoip_session_set_Remote_bandwidth(wx_cloudvoip_session_t session, int bandwidth)

/**
 * @brief Service-side join VoIP Room and create VoIP Session object
 *
 * Need to note:
 * This interface is used for server side requests https://api.weixin.qq.com/wxa/business/iot/voip/call Initiated Call Join
 * Service-side SDK Is singleton mode, you cannot create two or more simultaneous within a single process
 * wx_cloudvoip_session Examples. So you need to use the multi-process mode to call the server SDK.
 * It may also be involved here. IPC Requires vendor clouds to implement themselves.
 *
 * initiate VoIP Call Process:
 * 1. Server-side request https://api.weixin.qq.com/wxa/business/iot/voip/call Initiate a call
 * 2. WeChat background request manufacturer cloud background, notify cloud background has a new VoIP The session has been initiated
 * 3. Cloud backend call server SDK of wx_cloudvoip_session_cloud_call_Join Method Addition  VoIP conversation
 * 4. Cloud Backstage via audio_module, Camera_Module Streaming audio and video to the server SDK
 * 5. Service-side SDK The received audio and video stream is sent to the WeChat background, and then sent to the user's mobile phone WeChat
 *
 * @param  listener Session state callback
 * @param  user_Data Callback user data
 * @param  wxa_appid Mini Program AppId
 * @param  server_Token WeChat backstage to the cloud backstage notification VoIP The value with which the session originated
 * @param  roomid Room ID 
 * @param  session_key Room session _key
 * @param  payload Device side call wx_cloudvoip_client_call Function passed in payload
 * @param  session_out VoIP Session Results
 * @return
 *   - WXERROR_INVALID_ARGUMENT: Parameter error
 *   - WXERROR_FAILED_PRECONDITION: wx_init Not called or not completed.
 */
WX_API wx_operation_t
wx_cloudvoip_session_cloud_call_Join(wx_cloudvoip_session_type_t,
                          const struct wx_cloudvoip_session_listener* listener,
                          void* user_data,
                          const char* wxa_appid, 
                          const char* server_token,
                          const char* roomid,
                          const char* session_key,
                          const char* payload,
                          wx_cloudvoip_session_t* session_out)

WX_END_DECLS