vodafone-station-cli
Version:
Access your Vodafone Station from the comfort of the command line.
144 lines (143 loc) • 6.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Technicolor = void 0;
exports.normalizeChannelStatus = normalizeChannelStatus;
exports.normalizeUpstreamChannelStatus = normalizeUpstreamChannelStatus;
exports.normalizeUpstreamOfdmaChannelStatus = normalizeUpstreamOfdmaChannelStatus;
exports.normalizeOfdmChannelStatus = normalizeOfdmChannelStatus;
exports.normalizeDocsisStatus = normalizeDocsisStatus;
const modem_1 = require("./modem");
const crypto_1 = require("./tools/crypto");
function normalizeChannelStatus(channelStatus) {
return {
channelId: channelStatus.channelid,
channelType: channelStatus.ChannelType,
frequency: Number.parseInt(`${channelStatus.CentralFrequency ?? 0}`, 10),
lockStatus: channelStatus.locked,
modulation: (0, modem_1.normalizeModulation)(channelStatus.FFT),
powerLevel: Number.parseFloat(channelStatus.power),
snr: Number.parseFloat(`${channelStatus.SNR ?? 0}`),
};
}
function normalizeUpstreamChannelStatus(channelStatus) {
return {
channelId: channelStatus.channelidup,
channelType: channelStatus.ChannelType,
frequency: Number.parseInt(`${channelStatus.CentralFrequency ?? 0}`, 10),
lockStatus: channelStatus.RangingStatus,
modulation: (0, modem_1.normalizeModulation)(channelStatus.FFT),
powerLevel: Number.parseFloat(channelStatus.power),
snr: 0,
};
}
function normalizeUpstreamOfdmaChannelStatus(channelStatus) {
return {
channelId: channelStatus.channelidup,
channelType: channelStatus.ChannelType,
frequencyEnd: Number.parseFloat(channelStatus.end_frequency),
frequencyStart: Number.parseFloat(channelStatus.start_frequency),
lockStatus: channelStatus.RangingStatus,
modulation: (0, modem_1.normalizeModulation)(channelStatus.FFT),
powerLevel: Number.parseFloat(channelStatus.power),
snr: 0,
};
}
function normalizeOfdmChannelStatus(channelStatus) {
return {
channelId: channelStatus.channelid_ofdm,
channelType: channelStatus.ChannelType,
frequencyEnd: Number.parseInt(channelStatus.end_frequency, 10),
frequencyStart: Number.parseInt(channelStatus.start_frequency, 10),
lockStatus: channelStatus.locked_ofdm,
modulation: (0, modem_1.normalizeModulation)(channelStatus.FFT_ofdm),
powerLevel: Number.parseFloat(channelStatus.power_ofdm),
snr: Number.parseFloat(channelStatus.SNR_ofdm),
};
}
function normalizeDocsisStatus(channelStatus) {
return {
downstream: channelStatus.data.downstream.map(channel => normalizeChannelStatus(channel)),
downstreamOfdm: channelStatus.data.ofdm_downstream.map(channel => normalizeOfdmChannelStatus(channel)),
time: new Date().toISOString(),
upstream: channelStatus.data.upstream.map(channel => normalizeUpstreamChannelStatus(channel)),
upstreamOfdma: channelStatus.data.ofdma_upstream.map(channel => normalizeUpstreamOfdmaChannelStatus(channel)),
};
}
class Technicolor extends modem_1.Modem {
modemIp;
protocol;
logger;
constructor(modemIp, protocol, logger) {
super(modemIp, protocol, logger);
this.modemIp = modemIp;
this.protocol = protocol;
this.logger = logger;
}
async docsis() {
const { data: docsisStatus } = await this.httpClient.get('/api/v1/sta_docsis_status', {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Referer: this.baseUrl,
},
});
return normalizeDocsisStatus(docsisStatus);
}
async login(password) {
try {
const { data: salt } = await this.httpClient.post('/api/v1/session/login', `username=${modem_1.Modem.USERNAME}&password=seeksalthash`, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Referer: this.baseUrl,
},
});
this.logger.debug('Salt', salt);
if (salt.message && salt.message === 'MSG_LOGIN_150') {
throw new Error('A user is already logged in');
}
const derivedKey = (0, crypto_1.deriveKeyTechnicolor)((0, crypto_1.deriveKeyTechnicolor)(password, salt.salt), salt.saltwebui);
this.logger.debug('Derived key', derivedKey);
const { data: loginResponse } = await this.httpClient.post('/api/v1/session/login', `username=${modem_1.Modem.USERNAME}&password=${derivedKey}`, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Referer: this.baseUrl,
},
});
this.logger.debug('Login status', loginResponse);
const { data: messageResponse } = await this.httpClient.get('/api/v1/session/menu', {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Referer: this.baseUrl,
},
});
this.logger.debug('Message status', messageResponse);
}
catch (error) {
this.logger.warn(`Something went wrong with the login ${error}`);
}
}
async logout() {
this.logger.debug('Logging out...');
return this.httpClient.post('api/v1/session/logout');
}
async restart() {
const { data: tokenResponse } = await this.httpClient.get('api/v1/session/init_page', {
headers: {
Referer: this.baseUrl,
},
});
this.logger.debug('Token response: ', tokenResponse);
const { data: restartResponse } = await this.httpClient.post('api/v1/sta_restart', 'restart=Router%2CWifi%2CVoIP%2CDect%2CMoCA&ui_access=reboot_device', {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
Referer: this.baseUrl,
'X-CSRF-TOKEN': tokenResponse.token,
},
});
if (restartResponse?.error === 'error') {
this.logger.debug(restartResponse);
throw new Error(`Could not restart router: ${restartResponse.message}`);
}
return restartResponse;
}
}
exports.Technicolor = Technicolor;