Skip to content

Commit

Permalink
#721 - Adding download button for brew by weight & retrying the call …
Browse files Browse the repository at this point in the history
…to the xenia.
  • Loading branch information
graphefruit committed Jun 8, 2024
1 parent cefefd5 commit d75f745
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/app/settings/settings.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
<ion-label>{{"EXPORT" | translate}}</ion-label>
<ion-icon name="chevron-forward-outline" slot="end"></ion-icon>
</ion-item>
<ion-item *ngIf='doWeHaveBrewByWeights()' (click)='exportBrewByWeight()' button tappable>
<ion-label>Temp: Export Brew By Weight - Xenia</ion-label>
<ion-icon name="chevron-forward-outline" slot="end"></ion-icon>
</ion-item>
<ion-item (click)="excelExport()" button lines="none" tappable>
<ion-label>{{"EXCEL_EXPORT" | translate}}</ion-label>
<ion-icon name="chevron-forward-outline" slot="end"></ion-icon>
Expand Down
73 changes: 73 additions & 0 deletions src/app/settings/settings.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,15 @@ import { VisualizerService } from '../../services/visualizerService/visualizer-s
import { UIGraphStorage } from '../../services/uiGraphStorage.service';
import { Graph } from '../../classes/graph/graph';
import { TextToSpeechService } from '../../services/textToSpeech/text-to-speech.service';
import { PreparationDeviceType } from '../../classes/preparationDevice';
import { BrewFlow, IBrewWaterFlow } from '../../classes/brew/brewFlow';

declare var cordova: any;
declare var device: any;

declare var window: any;
declare var FilePicker;

@Component({
selector: 'settings',
templateUrl: './settings.page.html',
Expand Down Expand Up @@ -813,6 +816,7 @@ export class SettingsPage implements OnInit {
this.changeDetectorRef.detectChanges();
await this.uiSettingsStorage.saveSettings(this.settings);
}

public async visualizerServerHasChanged() {
if (this.settings.visualizer_server === VISUALIZER_SERVER_ENUM.VISUALIZER) {
this.settings.visualizer_url = 'https://visualizer.coffee/';
Expand All @@ -822,6 +826,7 @@ export class SettingsPage implements OnInit {
}
}
}

public async checkVisualizerURL() {
if (this.settings.visualizer_url === '') {
this.settings.visualizer_url = 'https://visualizer.coffee/';
Expand Down Expand Up @@ -878,6 +883,7 @@ export class SettingsPage implements OnInit {
);
}
}

public howManyBrewsAreNotUploadedToVisualizer() {
const brewEntries = this.uiBrewStorage.getAllEntries();
return brewEntries.filter(
Expand Down Expand Up @@ -1059,6 +1065,7 @@ export class SettingsPage implements OnInit {
const exportObjects: Array<any> = [...this.uiBrewStorage.getAllEntries()];
await this._exportFlowProfiles(exportObjects);
}

private async exportGraphProfiles() {
const exportObjects: Array<any> = [...this.uiGraphStorage.getAllEntries()];
await this._exportGraphProfiles(exportObjects);
Expand Down Expand Up @@ -1177,6 +1184,71 @@ export class SettingsPage implements OnInit {
this.uiExcel.export();
}

public doWeHaveBrewByWeights(): boolean {
const allPreparations = this.uiPreparationStorage.getAllEntries();
for (const prep of allPreparations) {
if (
prep.connectedPreparationDevice.type === PreparationDeviceType.XENIA
) {
return true;
}
}
}

public async exportBrewByWeight() {
await this.uiAlert.showLoadingSpinner();
try {
const allXeniaPreps = [];
const allPreparations = this.uiPreparationStorage.getAllEntries();
for (const prep of allPreparations) {
if (
prep.connectedPreparationDevice.type === PreparationDeviceType.XENIA
) {
allXeniaPreps.push(prep);
}
}

const allBrewsWithProfiles = this.uiBrewStorage
.getAllEntries()
.filter(
(e) =>
e.flow_profile !== null &&
e.flow_profile !== undefined &&
e.flow_profile !== '' &&
allXeniaPreps.find(
(pr) => pr.config.uuid === e.method_of_preparation
) &&
e.preparationDeviceBrew &&
e.preparationDeviceBrew.params &&
e.preparationDeviceBrew.params.brew_by_weight_active === true
);

const allBrewFlows: Array<{ BREW: Brew; FLOW: BrewFlow }> = [];
for await (const brew of allBrewsWithProfiles) {
const flow: BrewFlow = await this.readFlowProfile(brew);

allBrewFlows.push({
BREW: brew,
FLOW: flow,
});
}

this.uiExcel.exportBrewByWeights(allBrewFlows);
} catch (ex) {
this.uiAlert.hideLoadingSpinner();
}
}

public async readFlowProfile(_brew: Brew) {
const flowProfilePath = 'brews/' + _brew.config.uuid + '_flow_profile.json';
try {
const jsonParsed = await this.uiFileHelper.getJSONFile(flowProfilePath);
return jsonParsed as BrewFlow;
} catch (ex) {
return null;
}
}

public importBeansExcel(): void {
if (this.platform.is('cordova')) {
this.uiAnalytics.trackEvent(
Expand Down Expand Up @@ -1463,6 +1535,7 @@ export class SettingsPage implements OnInit {
}
}
}

private async _importGraphProfileFiles(
_storedData: Array<Graph>,
_importPath: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2177,6 +2177,35 @@ export class BrewBrewingGraphComponent implements OnInit {
false
);
});

setTimeout(() => {
prepDeviceCall.getOverview().then(
(_jsonResp: any) => {
if (_jsonResp.MA_Status === 3) {
//Great we started.
} else {
//Oh no... lets try it again
this.uiToast.showInfoToast(
'We tried to start the xenia script again'
);
prepDeviceCall
.startScript(
this.data.preparationDeviceBrew.params.scriptStartId
)
.catch((_msg) => {
this.uiLog.log('We could not start script: ' + _msg);
this.uiToast.showInfoToast(
'We could not start script - second try: ' + _msg,
false
);
});
}
},
() => {
//Error... ignore
}
);
}, 1000);
this.writeExecutionTimeToNotes(
'Start script',
this.data.preparationDeviceBrew.params.scriptStartId,
Expand Down
135 changes: 134 additions & 1 deletion src/services/uiExcel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ import { UIAlert } from './uiAlert';
import { SocialSharing } from '@awesome-cordova-plugins/social-sharing/ngx';
import { UIFileHelper } from './uiFileHelper';
import { UIMillStorage } from './uiMillStorage';
import { BrewFlow } from '../classes/brew/brewFlow';
import { BrewFlow, IBrewWaterFlow } from '../classes/brew/brewFlow';
import moment from 'moment';
import { UISettingsStorage } from './uiSettingsStorage';
import { Settings } from '../classes/settings/settings';
import { Brew } from '../classes/brew/brew';

@Injectable({
providedIn: 'root',
Expand Down Expand Up @@ -544,6 +545,138 @@ export class UIExcel {
await this.uiAlert.hideLoadingSpinner();
}

public async exportBrewByWeights(
_entry: Array<{ BREW: Brew; FLOW: BrewFlow }>
) {
await this.uiAlert.showLoadingSpinner();

let counter: number = 0;

const wb: XLSX.WorkBook = XLSX.utils.book_new();
for (const exportEntry of _entry) {
const grindWeight = exportEntry.BREW.grind_weight;
const brewBeverageQuantity = exportEntry.BREW.brew_beverage_quantity;
const avgFlow: number = this.getAvgFlow(exportEntry.FLOW);
if (exportEntry.FLOW.hasOwnProperty('brewbyweight')) {
const header_final_weight: Array<string> = [];
header_final_weight.push('target_weight');
header_final_weight.push('lag_time');
header_final_weight.push('brew_time');
header_final_weight.push('timestamp');
header_final_weight.push('last_flow_value');
header_final_weight.push('actual_scale_weight');
header_final_weight.push('calc_lag_time');
header_final_weight.push('calc_exceeds_weight');
header_final_weight.push('avg_flow_lag_residual_time');
header_final_weight.push('residual_lag_time');
header_final_weight.push('average_flow_rate');
header_final_weight.push('scaleType');
header_final_weight.push('grindWeight');
header_final_weight.push('brewBeverageQuantity');
header_final_weight.push('avgFlow');
header_final_weight.push('offsetWeight');
header_final_weight.push('offsetWeightPercentage');

const wsDatafinalWeightFlow: any[][] = [header_final_weight];
for (const entry of exportEntry.FLOW.brewbyweight) {
let percentageOffset =
(Number(brewBeverageQuantity) * 100) / Number(entry.target_weight);
if (percentageOffset >= 100) {
percentageOffset = percentageOffset - 100;
} else {
percentageOffset = (percentageOffset - 100) * -1;
}
const wbEntry: Array<any> = [
entry.target_weight,
entry.lag_time,
entry.brew_time,
entry.timestamp,
entry.last_flow_value,
entry.actual_scale_weight,
entry.calc_lag_time,
entry.calc_exceeds_weight,
entry.avg_flow_lag_residual_time,
entry.residual_lag_time,
entry.average_flow_rate,
entry.scaleType,
grindWeight,
brewBeverageQuantity,
avgFlow,
Number(entry.target_weight) - Number(brewBeverageQuantity),
Number(percentageOffset),
];
wsDatafinalWeightFlow.push(wbEntry);
}
const wsFinalWeight: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(
wsDatafinalWeightFlow
);
XLSX.utils.book_append_sheet(wb, wsFinalWeight, 'S-' + counter);
counter = counter + 1;
}
}

const filename: string =
'Beanconqueror_All_Brew_ByWeights_' +
moment().format('HH_mm_ss_DD_MM_YYYY').toString() +
'.xlsx';
try {
/* generate Blob */
const wbout: ArrayBuffer = XLSX.write(wb, {
bookType: 'xlsx',
type: 'array',
});
const blob: Blob = new Blob([wbout], {
type: 'application/octet-stream',
});
try {
const downloadFile: FileEntry = await this.uiFileHelper.downloadFile(
filename,
blob,
true
);
await this.uiAlert.hideLoadingSpinner();
// We share directly, so we don'T download into download folders.
/**if (this.platform.is('android')) {
const alert = await this.alertCtrl.create({
header: this.translate.instant('DOWNLOADED'),
subHeader: this.translate.instant('FILE_DOWNLOADED_SUCCESSFULLY', {
fileName: filename,
}),
buttons: ['OK'],
});
await alert.present();
}**/
} catch (ex) {}
} catch (e) {
if (e.message.match(/It was determined/)) {
/* in the browser, use writeFile */
XLSX.writeFile(wb, filename);
} else {
this.uiAlert.showMessage(e.message);
this.uiLog.log(`Excel export - Error occured: ${e.message}`);
}
}
await this.uiAlert.hideLoadingSpinner();
}
private getAvgFlow(_flow: BrewFlow): number {
if (_flow.waterFlow && _flow.waterFlow.length > 0) {
const waterFlows: Array<IBrewWaterFlow> = _flow.waterFlow;
let calculatedFlow: number = 0;
let foundEntries: number = 0;
for (const water of waterFlows) {
if (water.value > 0) {
calculatedFlow += water.value;
foundEntries += 1;
}
}
if (calculatedFlow > 0) {
return calculatedFlow / foundEntries;
}

return 0;
}
}

public async importBeansByExcel(_arrayBuffer) {
try {
/* data is an ArrayBuffer */
Expand Down

0 comments on commit d75f745

Please sign in to comment.