{"version":3,"sources":["jsdelivr-header.js","/npm/node-dahua-api-zhoukai@1.1.7/dahua.js"],"names":[],"mappings":"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","file":"/npm/node-dahua-api-zhoukai@1.1.7/dahua.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/node-dahua-api-zhoukai@1.1.7/dahua.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","#!/usr/bin/nodejs\n// Dahua HTTP API Module\n\nvar net = require(\"net\");\nvar events = require(\"events\");\nvar util = require(\"util\");\nvar request = require(\"request\");\nvar NetKeepAlive = require(\"net-keepalive\");\nconst md5 = require(\"md5\");\nconst { v4 } = require(\"uuid\");\n\nvar TRACE = true;\nvar BASEURI = false;\n// 重试次数 (发送两次请求)\nvar RetryCount = 0;\n\nvar dahua = function (options) {\n  this.options = options;\n  (this.auth = {\n    user: options.user,\n    pass: options.pass,\n    sendImmediately: false,\n  }),\n    events.EventEmitter.call(this);\n  this.client = this.connect(options);\n  TRACE = options.log;\n  BASEURI = \"http://\" + options.host + \":\" + options.port;\n};\n\nutil.inherits(dahua, events.EventEmitter);\n\ndahua.prototype.connect = function (options, headerParams) {\n  var self = this;\n  // var authHeader =\n  //   \"Basic \" + new Buffer(options.user + \":\" + options.pass).toString(\"base64\");\n  // Connect\n  var client = net.connect(options, function () {\n    RetryCount += 1;\n    var header =\n      \"GET /cgi-bin/eventManager.cgi?action=attach&codes=[AlarmLocal,VideoMotion,VideoLoss,VideoBlind] HTTP/1.0\\r\\n\" +\n      \"Host: \" +\n      options.host +\n      \":\" +\n      options.port +\n      \"\\r\\n\" +\n      headerParams +\n      \"\\r\\n\" +\n      \"Accept: multipart/x-mixed-replace\\r\\n\\r\\n\";\n    client.write(header);\n    console.log(\"dahua.prototype.connect -> client\", header);\n    client.setKeepAlive(true, 1000);\n    NetKeepAlive.setKeepAliveInterval(client, 5000); // sets TCP_KEEPINTVL to 5s\n    NetKeepAlive.setKeepAliveProbes(client, 12); // 60s and kill the connection.\n    handleConnection(self, options);\n  });\n\n  client.on(\"timeout\", function () {\n    console.log(\"10 mins of inactivity\");\n    //self.abort()\n    //self.connect(options)\n  });\n\n  client.on(\"data\", function (data) {\n    handleData(self, data, options);\n  });\n\n  client.on(\"close\", function () {\n    // Try to reconnect after 30s\n    // setTimeout(function () {\n    //   self.connect(options);\n    // }, 30000);\n    handleEnd(self);\n  });\n\n  client.on(\"error\", function (err) {\n    handleError(self, err);\n  });\n};\n\ndahua.prototype.ptzCommand = function (cmd, arg1, arg2, arg3, arg4) {\n  var self = this;\n  if (!cmd || isNaN(arg1) || isNaN(arg2) || isNaN(arg3) || isNaN(arg4)) {\n    handleError(self, \"INVALID PTZ COMMAND\");\n    return 0;\n  }\n  request(\n    BASEURI +\n      \"/cgi-bin/ptz.cgi?action=start&channel=0&code=\" +\n      ptzcommand +\n      \"&arg1=\" +\n      arg1 +\n      \"&arg2=\" +\n      arg2 +\n      \"&arg3=\" +\n      arg3 +\n      \"&arg4=\" +\n      arg4,\n    function (error, response, body) {\n      if (error || response.statusCode !== 200 || body.trim() !== \"OK\") {\n        self.emit(\"error\", \"FAILED TO ISSUE PTZ COMMAND\");\n      }\n    }\n  );\n};\n\ndahua.prototype.ptzPreset = function (preset) {\n  var self = this;\n  if (isNaN(preset)) handleError(self, \"INVALID PTZ PRESET\");\n  request(\n    BASEURI +\n      \"/cgi-bin/ptz.cgi?action=start&channel=0&code=GotoPreset&arg1=0&arg2=\" +\n      preset +\n      \"&arg3=0\",\n    function (error, response, body) {\n      if (error || response.statusCode !== 200 || body.trim() !== \"OK\") {\n        self.emit(\"error\", \"FAILED TO ISSUE PTZ PRESET\");\n      }\n    }\n  );\n};\n\ndahua.prototype.ptzZoom = function (multiple) {\n  var self = this;\n  if (isNaN(multiple)) handleError(self, \"INVALID PTZ ZOOM\");\n  if (multiple > 0) cmd = \"ZoomTele\";\n  if (multiple < 0) cmd = \"ZoomWide\";\n  if (multiple === 0) return 0;\n\n  request(\n    BASEURI +\n      \"/cgi-bin/ptz.cgi?action=start&channel=0&code=\" +\n      cmd +\n      \"&arg1=0&arg2=\" +\n      multiple +\n      \"&arg3=0\",\n    function (error, response, body) {\n      if (error || response.statusCode !== 200 || body.trim() !== \"OK\") {\n        self.emit(\"error\", \"FAILED TO ISSUE PTZ ZOOM\");\n      }\n    }\n  );\n};\n\ndahua.prototype.ptzMove = function (err, success, direction, action, speed) {\n  console.log(\"dahua.prototype.ptzMove -> action\", action);\n  var self = this;\n  if (isNaN(speed)) {\n    err(\"INVALID PTZ SPEED\");\n    // handleError(self, \"INVALID PTZ SPEED\")\n  }\n  if (action !== \"start\" && action !== \"stop\") {\n    err(\"INVALID PTZ COMMAND\");\n    // handleError(self, \"INVALID PTZ COMMAND\");\n    return 0;\n  }\n  if (\n    direction !== \"Up\" &&\n    direction !== \"Down\" &&\n    direction !== \"Left\" &&\n    direction !== \"Right\" &&\n    direction !== \"LeftUp\" &&\n    direction !== \"RightUp\" &&\n    direction !== \"LeftDown\" &&\n    direction !== \"RightDown\"\n  ) {\n    err(\"INVALID PTZ DIRECTION\");\n    // handleError(self, \"INVALID PTZ DIRECTION\");\n    return 0;\n  }\n  const options = {\n    url:\n      BASEURI +\n      \"/cgi-bin/ptz.cgi?action=\" +\n      action +\n      \"&channel=0&code=\" +\n      direction +\n      \"&arg1=\" +\n      speed +\n      \"&arg2=\" +\n      speed +\n      \"&arg3=0\",\n    auth: this.auth,\n  };\n  RequestFun(options.url, options.auth)\n    .then(function (res) {\n      success(res);\n    })\n    .catch(function (error) {\n      err(error);\n    });\n};\n\ndahua.prototype.ptzStatus = function () {\n  var self = this;\n  request(BASEURI + \"/cgi-bin/ptz.cgi?action=getStatus\", function (\n    error,\n    response,\n    body\n  ) {\n    if (!error && response.statusCode === 200) {\n      body = body.toString().split(\"\\r\\n\");\n      self.emit(\"ptzStatus\", body);\n    } else {\n      self.emit(\"error\", \"FAILED TO QUERY STATUS\");\n    }\n  });\n};\n\ndahua.prototype.dayProfile = function () {\n  var self = this;\n  request(\n    BASEURI +\n      \"/cgi-bin/configManager.cgi?action=setConfig&VideoInMode[0].Config[0]=1\",\n    function (error, response, body) {\n      if (!error && response.statusCode === 200) {\n        if (body === \"Error\") {\n          // Didnt work, lets try another method for older cameras\n          request(\n            BASEURI +\n              \"/cgi-bin/configManager.cgi?action=setConfig&VideoInOptions[0].NightOptions.SwitchMode=0\",\n            function (error, response, body) {\n              if (error || response.statusCode !== 200) {\n                self.emit(\"error\", \"FAILED TO CHANGE TO DAY PROFILE\");\n              }\n            }\n          );\n        }\n      } else {\n        self.emit(\"error\", \"FAILED TO CHANGE TO DAY PROFILE\");\n      }\n    }\n  );\n};\n\ndahua.prototype.nightProfile = function () {\n  var self = this;\n  request(\n    BASEURI +\n      \"/cgi-bin/configManager.cgi?action=setConfig&VideoInMode[0].Config[0]=2\",\n    function (error, response, body) {\n      if (!error && response.statusCode === 200) {\n        if (body === \"Error\") {\n          // Didnt work, lets try another method for older cameras\n          request(\n            BASEURI +\n              \"/cgi-bin/configManager.cgi?action=setConfig&VideoInOptions[0].NightOptions.SwitchMode=3\",\n            function (error, response, body) {\n              if (error || response.statusCode !== 200) {\n                self.emit(\"error\", \"FAILED TO CHANGE TO NIGHT PROFILE\");\n              }\n            }\n          );\n        }\n      } else {\n        self.emit(\"error\", \"FAILED TO CHANGE TO NIGHT PROFILE\");\n      }\n    }\n  );\n};\n\nfunction handleData(self, data, options) {\n  if (TRACE) console.log(\"Data: \" + data);\n  data = data.toString().split(\"\\r\\n\");\n  var i = Object.keys(data);\n  i.forEach(function (id) {\n    if (data[id] === \"HTTP/1.1 401 Unauthorized\") {\n      if (RetryCount <= 3) {\n        console.log(\"handleData -> data[1]\", data[1]);\n        generateAuthorization(data[1], options.user, options.pass, function (\n          params\n        ) {\n          console.log(\"handleData -> headerParmas\", params);\n          self.connect(options, params);\n        });\n      }\n    }\n    if (data[id].startsWith(\"Code=\")) {\n      var alarm = data[id].split(\";\");\n      var code = alarm[0].substr(5);\n      var action = alarm[1].substr(7);\n      var index = alarm[2].substr(6);\n      self.emit(\"alarm\", code, action, index);\n    }\n  });\n}\n\nfunction handleConnection(self, options) {\n  if (TRACE) console.log(\"Connected to \" + options.host + \":\" + options.port);\n  //self.socket = socket;\n  self.emit(\"connect\");\n}\n\nfunction handleEnd(self) {\n  if (TRACE) console.log(\"Connection closed!\");\n  self.emit(\"end\");\n}\n\nfunction handleError(self, err) {\n  if (TRACE) console.log(\"Connection error: \" + err);\n  RetryCount = 0;\n  self.emit(\"error\", err);\n}\n\n/**\n * 根据返回的头信息 生成验证信息头\n * @param {*} data 数据\n * @param {*} username 用户名\n * @param {*} password 密码\n * @param {*} callback 回调\n */\nfunction generateAuthorization(data, username, password, callback) {\n  // 最终结果值\n  const endParams = {\n    realm: \"\",\n    qop: \"\",\n    nonce: \"\",\n    opaque: \"\",\n    cnonce: v4().replace(/-/gi, \"\"),\n    nc: \"00000001\",\n  };\n  console.log(\"data\", data);\n  console.log(\"\\n\");\n  const rr = data.replace(\"WWW-Authenticate\", \"Authenticate\");\n\n  rr.split(\",\").forEach((item) => {\n    let r = item.trim().replace(/=/gi, \":\");\n    if (foramtParams(r, \"realm:\")) endParams.realm = foramtParams(r, \"realm:\");\n    if (foramtParams(r, \"qop:\")) endParams.qop = foramtParams(r, \"qop:\");\n    if (foramtParams(r, \"nonce:\")) endParams.nonce = foramtParams(r, \"nonce:\");\n    if (foramtParams(r, \"opaque:\"))\n      endParams.opaque = foramtParams(r, \"opaque:\");\n  });\n  /**\n   * 获取参数时的处理\n   * @param {*} data 数据\n   * @param {*} val 选择搜索的值\n   */\n  function foramtParams(data, val) {\n    if (data.indexOf(val) !== -1 || data.indexOf(val) === 0) {\n      return data.substring(data.indexOf(val) + val.length).replace(/\"/gi, \"\");\n    }\n    return false;\n  }\n\n  // HA1部分\n  const HA1 = md5(`${username}:${endParams.realm}:${password}`);\n\n  // HA2\n  const HA2 = md5(\"GET:192.168.33.241:80\");\n  const response = md5(\n    `${HA1}:${endParams.nonce}:${endParams.nc}:${endParams.cnonce}:${endParams.qop}:${HA2}`\n  );\n  const returnValidationHeader = `Authorization: Digest username=\"${username}\",realm=\"${endParams.realm}\",nonce=\"${endParams.nonce}\",uri=\"192.168.33.241:80\",algorithm=\"MD5\",cnonce=\"${endParams.cnonce}\",nc=\"${endParams.nc}\",qop=\"${endParams.qop}\",response=\"${response}\"`;\n  callback(returnValidationHeader);\n}\n\n/**\n * 通用request请求\n * @param {*} url 地址\n * @param {*} auth 验证\n */\nfunction RequestFun(url, auth) {\n  return new Promise(function (resolve, reject) {\n    const options = {\n      url,\n      auth,\n    };\n    request(options, function (error, response, body) {\n      if (error || response.statusCode !== 200 || body.trim() !== \"OK\") {\n        reject({\n          msg: response.statusMessage,\n          code: response.statusCode,\n        });\n      } else {\n        resolve(response.statusMessage);\n      }\n    });\n  });\n}\n\nString.prototype.startsWith = function (str) {\n  return this.slice(0, str.length) == str;\n};\n\nexports.dahua = dahua;\n"]}