|
楼主 |
发表于 2020-12-3 20:18
|
显示全部楼层
cpp源代码
#ifndef LWIP_OPEN_SRC
#define LWIP_OPEN_SRC
#endif
#include <functional>
#include "ESP8266SSDP.h"
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h> // http ->tcp
#include "WiFiUdp.h"
#include "debug.h"
#include <WiFiClientSecure.h>
extern "C" {
#include "osapi.h"
#include "ets_sys.h"
#include "user_interface.h"
}
#include "lwip/opt.h"
#include "lwip/udp.h"
#include "lwip/inet.h"
#include "lwip/igmp.h"
#include "lwip/mem.h"
#include "include/UdpContext.h"
#define DEBUG_SSDP Serial
#define SSDP_PORT 1900
#define SSDP_BUFFER_SIZE 64
#define SSDP_MULTICAST_ADDR 239, 255, 255, 250
static const char _ssdp_response_template[] PROGMEM =
"HTTP/1.1 200 OK\r\n"
"EXT:\r\n";
static const char _dlna_tcpsend_template[] PROGMEM =
"POST /AVTransport/%s/control.xml HTTP/1.1\r\n"
"HOST: %s:%d\r\n"
"CONTENT-LENGTH: %d\r\n"
"CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n"
"SOAPACTION: \"urn:schemas-upnp-org:service:AVTransport:1#%s\"\r\n"
"USER-AGENT: Linux/3.3.0, UPnP/1.0, libupnp/1.6.19\r\n"
"\r\n";
static const char _ssdp_search_template[] PROGMEM =
"M-SEARCH * HTTP/1.1\r\n"
"User-Agent: E:\mypy\dlna.py/0.15\r\n"
"HOST: 239.255.255.250:1900\r\n"
"Accept: */*\r\n"
"MAN: \"ssdp:discover\"\r\n"
"ST: %s\r\n"
"MX: 3\r\n"
"\r\n";
static const char _dlna_action_template[] PROGMEM =
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body><u:%s xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\r\n"
"<InstanceID>0</InstanceID>\r\n"
"<Speed>1</Speed>\r\n"
"</u:%s>\r\n"
"</s:Body>\r\n"
"</s:Envelope>\r\n";
static const char _dlna_playuri_template[] PROGMEM =
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
"<s:Body><u:SetAVTransportURI xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\r\n"
"<InstanceID>0</InstanceID>\r\n"
"<CurrentURI>%s</CurrentURI>\r\n"
"<CurrentURIMetaData><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"><item id="123" parentID="-1" restricted="1"><upnp:storageMedium>UNKNOWN</upnp:storageMedium><upnp:writeStatus>UNKNOWN</upnp:writeStatus><upnp:class>object.item.videoItem</upnp:class><dc:title>....-vip.................</dc:title><dc:creator>youku</dc:creator><res protocolInfo="http-get:*:video/mp4:*;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01700000000000000000000000000000">%s</res><yunos os="android" ver="4.5.1.151" name="......" pkg="com.quark.browser" proj_mode="NORMAL_2" yk_vid="16062670667400001" yk_showtitle="NULL" yk_showid="NULL" duration="37245330" startpos="0" definition="NULL" /></item></DIDL-Lite></CurrentURIMetaData>\r\n"
"</u:SetAVTransportURI>\r\n"
"</s:Body>\r\n"
"</s:Envelope>\r\n";
SSDPClass::SSDPClass(){
_port=80;
_pending=false;
}
SSDPClass::~SSDPClass() {
end();
}
bool SSDPClass::begin() {
end();
_server = new UdpContext;
_server->ref();
IPAddress local = WiFi.localIP();
IPAddress mcast(SSDP_MULTICAST_ADDR);
if (igmp_joingroup(local, mcast) != ERR_OK ) {
#ifdef DEBUG_SSDP
DEBUG_SSDP.printf_P(PSTR("SSDP failed to join igmp group\n"));
#endif
return false;
}
if (!_server->listen(IP_ADDR_ANY, SSDP_PORT)) {
return false;
}
_server->setMulticastInterface(local);
_server->setMulticastTTL(2);
_server->onRx(std::bind(&SSDPClass::update, this));
if (!_server->connect(mcast, SSDP_PORT)) {
return false;
}
return true;
}
void SSDPClass::end() {
if(!_server)
return;
_server->disconnect();
IPAddress local = WiFi.localIP();
IPAddress mcast(SSDP_MULTICAST_ADDR);
_server->unref();
_server = 0;
}
void SSDPClass::update() {
if (!_pending && _server->next()) {
uint8_t cursor = 0;
uint8_t cr = 0;
char buffer[255] = {0};
bool location = false;
bool server = false ;
bool uuid= false ;
char ip[4];
uint8_t ip1;
uint8_t ip2;
uint8_t ip3;
uint8_t ip4;
char ipport[5];
while (_server->getSize() > 0) {
char c = _server->read();
if(strcasecmp(buffer,"serv") == 0){
cursor=0;
do{
c = _server->read();
}while(c != ' ');
do{
c = _server->read();
buffer[cursor++] = c;
buffer[cursor] ='\0';
}while( c != '\r' && c != '\n' );
for(int i=0;i<strlen(buffer);i++){
buffer[i] = tolower(buffer[i]);
}
if (strstr(buffer,"dlna") > 0){
server = true;
}
}
if(strcasecmp(buffer,"Loca") == 0){
cursor=0;
do{
c = _server->read();
}while(c != ' ');
do{
c = _server->read();
buffer[cursor++] = c;
buffer[cursor] ='\0';
}while( c != '\r' && c != '\n' );
int j=7;
int k;
do{
ip[j-7] = buffer[j];
ip[j-6] = '\0';
j++;
}while(buffer[j] !='.');
ip1 = atoi(ip);
j++;
k = j;
do{
ip[j-k] = buffer[j];
ip[j-k+1] ='\0';
j++;
}while(buffer[j] !='.' );
ip2 = atoi(ip);
j++;
k = j;
do{
ip[j-k] = buffer[j];
ip[j-k+1] ='\0';
j++;
}while(buffer[j] !='.' );
ip3 = atoi(ip);
j++;
k = j;
do{
ip[j-k] = buffer[j];
ip[j-k+1] ='\0';
j++;
}while(buffer[j] !=':' );
ip4 = atoi(ip);
j++;
k = j;
do{
ipport[j-k] = buffer[j];
ipport[j-k+1] ='\0';
j++;
}while(buffer[j] !='/' && j < strlen(buffer) );
_remoteAddr = IPAddress(ip1,ip2,ip3,ip4);
_remotePort = atoi(ipport);
location= true;
}
if(strncmp("USN:",buffer,4)==0){
cursor=0;
do{
c = _server->read();
}while(c != ' ');
do{
c = _server->read();
buffer[cursor++] = c;
buffer[cursor] ='\0';
}while( c != '\r' && c != '\n');
char fuuid[4];
fuuid[0] = buffer[0];
fuuid[1] = buffer[1];
fuuid[2] = buffer[2];
fuuid[3] = buffer[3];
fuuid[4] = '\0';
if (strcasecmp(fuuid,"uuid")==0){
for( int a = 0; a < 60; a =a +1 ){
if (buffer[5+a] != ':' && buffer[5+a] != '\r' && buffer[5+a] != '\n' ){
tuuid[a] = buffer[5+a];
}else{
tuuid[a] = '\0';
}
}
uuid=true;
}
};
if(cursor < 4){
buffer[cursor++] = c;
buffer[cursor] = '\0';
}
if(c=='\r' || c=='\n'){
cursor = 0;
}
if (uuid && server && location){
_pending = true;
_havetv = true;
DEBUG_SSDP.printf("location:%d,%d,%d,%d\r\n",ip1,ip2,ip3,ip4);
DEBUG_SSDP.printf("uuid:%s\r\n",(char*)tuuid);
}
}
//_server->flush();
}
if (_pending) {
while (_server->next())
_server->flush();
}
}
void SSDPClass::http_send(){
DEBUG_SSDP.printf("???");
WiFiClient clients;
if (!clients.connect(_remoteAddr,_remotePort)) { // 判断连接情况
DEBUG_SSDP.print("connection failed/r/n");
return;
}
char bui[2000];
char bu[640];
int len;
//停止
len = snprintf_P(bui, sizeof(bui),
_dlna_action_template,
"Stop",
"Stop"
);
len = snprintf_P(bu, sizeof(bu),
_dlna_tcpsend_template,
tuuid,
_remoteAddr.toString().c_str(),
_remotePort,
len,
"Stop"
);
clients.print(bu);
clients.print(bui);
//uri
len = snprintf_P(bui, sizeof(bui),
_dlna_playuri_template,
"https://youku.com-t-youku.com/20190325/10676_9a90c151/index.m3u8?dlnaopt=2&tpseq=1",
"https://youku.com-t-youku.com/20190325/10676_9a90c151/index.m3u8?dlnaopt=2&tpseq=1"
);
len = snprintf_P(bu, sizeof(bu),
_dlna_tcpsend_template,
tuuid,
_remoteAddr.toString().c_str(),
_remotePort,
len,
"SetAVTransportURI"
);
clients.print(bu);
clients.print(bui);
//播放
len = snprintf_P(bui, sizeof(bui),
_dlna_action_template,
"Play",
"Play"
);
len = snprintf_P(bu, sizeof(bu),
_dlna_tcpsend_template,
tuuid,
_remoteAddr.toString().c_str(),
_remotePort,
len,
"Play"
);
clients.print(bu);
clients.print(bui);
DEBUG_SSDP.print("运行完了,去看看");
DEBUG_SSDP.print("\r\n");
}
void SSDPClass::send() {
DEBUG_SSDP.print("寻找.....\r\n");
char buffer[1460];
IPAddress ip = WiFi.localIP();
IPAddress remoteAddr;
uint16_t remotePort;
remoteAddr = IPAddress(SSDP_MULTICAST_ADDR);
remotePort = SSDP_PORT;
int len = snprintf_P(buffer, sizeof(buffer),
_ssdp_search_template,
"ssdp:all"
);
_server->append(buffer, len);
_server->send(remoteAddr, remotePort);
len = snprintf_P(buffer, sizeof(buffer),
_ssdp_search_template,
"urn:schemas-upnp-org:device:AVTransport:1"
);
_server->append(buffer, len);
_server->send(remoteAddr, remotePort);
len = snprintf_P(buffer, sizeof(buffer),
_ssdp_search_template,
"urn:schemas-upnp-org:device:MediaRenderer:1"
);
_server->append(buffer, len);
_server->send(remoteAddr, remotePort);
len = snprintf_P(buffer, sizeof(buffer),
_ssdp_search_template,
"urn:schemas-upnp-org:device:MediaServer:1"
);
_server->append(buffer, len);
_server->send(remoteAddr, remotePort);
}
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SSDP)
SSDPClass SSDP;
#endif
|
|