if (breakdown.offline) tooltips.push(`${formatCurrency(breakdown.offline.cost)} (Offline)`);
tbSmPUi.results.innerHTML = `
-
-
-
- Calculation summary
-
- ${copyIcon}
- ${downloadIcon}
-
+
+
+ Calculation summary
+
+ ${copyIcon}
+ ${downloadIcon}
+
+
${detailsHtml}
Add-ons
${addonsHtml}
@@ -478,11 +504,11 @@ Calculation summary
if (tbSmPState.addons.edge.enabled && breakdown.edge) {
const edge = breakdown.edge;
const content = `
- ${tbSmPCreateItem('Add-on Base Price', formatCurrency(edge.base))}
- ${tbSmPCreateItem('Included Edges', edge.included)}
+ ${tbSmPCreateItem('Included Edges', edge.included, 'Number of Edge instances covered by the Edge Computing add-on base price.')}
+ ${tbSmPCreateItem('Add-on Base Price', formatCurrency(edge.base), 'One-time base fee for the Edge Computing add-on.')}
${edge.extra > 0 ? tbSmPCreateItem('Extra Edges', edge.extra) + tbSmPCreateItem('Extra Edges Cost', formatCurrency(edge.extraCost)) : ''}
`;
- html += section('edgeComputing', 'Edge Computing', `${formatCurrency(edge.cost)}${infoIcon}Edge Computing add-on`, 'expandable', content);
+ html += section('edgeComputing', 'Edge Computing', `${formatCurrency(edge.cost)}${infoIcon}Total one-time Edge Computing cost. Calculation: ${formatCurrency(edge.cost)} = ${formatCurrency(edge.base)} (base) + ${formatCurrency(edge.extraCost)} (extra edges)`, 'expandable', content);
} else {
html += addButton('edge', 'Edge Computing', plan.edgeMonthPrice);
}
@@ -491,11 +517,12 @@ Calculation summary
const trendz = breakdown.trendz;
const hasExtra = trendz.extraDevices > 0;
const content = hasExtra ? `
- ${tbSmPCreateItem('Add-on Base Price', formatCurrency(trendz.base))}
+ ${tbSmPCreateItem('Included Devices', formatNumber(plan.includedDevices), 'Number of devices covered by the Trendz perpetual license base price.')}
+ ${tbSmPCreateItem('Add-on Base Price', formatCurrency(trendz.base), 'Base cost for the Trendz Analytics add-on.')}
${tbSmPCreateItem('Extra Devices', trendz.extraDevices)}
${tbSmPCreateItem('Extra Devices Cost', formatCurrency(trendz.extraCost))}
` : '';
- html += section('trendzAnalytics', 'Trendz Analytics', `${formatCurrency(trendz.cost)}${infoIcon}Trendz Analytics add-on`, hasExtra ? 'expandable' : '', content);
+ html += section('trendzAnalytics', 'Trendz Analytics', `${formatCurrency(trendz.cost)}${infoIcon}Total one-time Trendz cost. ${formatCurrency(trendz.cost)} = ${formatCurrency(trendz.base)} (base price) + ${formatCurrency(trendz.extraCost)} (extra devices)`, hasExtra ? 'expandable' : '', content);
} else {
html += addButton('trendz', 'Trendz Analytics', plan.trendzMonthPrice);
}
@@ -504,7 +531,7 @@ Calculation summary
html += `
Offline Mode
- ${formatCurrency(breakdown.offline.cost)}${infoIcon}One-time offline mode license
+ ${formatCurrency(breakdown.offline.cost)}${infoIcon}Enables full platform functionality in environments without internet connection.
`;
} else {
@@ -533,10 +560,12 @@ Calculation summary
});
};
- const tbSmPUpdateClipboard = ({ plan, devices, extraDevices, extraDevicesCost, extraProd, extraProdCost, devCost, breakdown, totalPrice }) => {
+ const tbSmPUpdateClipboard = ({ plan, devices, extraDevices, extraDevicesCost, complimentaryProd, extraProd, extraProdCost, devCost, breakdown, totalPrice }) => {
let msg = `Perpetual License: ${plan.name} (${formatCurrency(plan.price)})\n`;
msg += `- Devices: ${formatNumber(devices)}\n`;
- msg += `- Prod Instances: ${formatNumber(tbSmPState.prodInstances)}\n`;
+ msg += `- Prod Instances: ${formatNumber(tbSmPState.prodInstances)}`;
+ if (complimentaryProd > 0) msg += ` (${plan.includedProdInstances} included + ${complimentaryProd} complimentary)`;
+ msg += '\n';
msg += `- Dev Instances: ${formatNumber(tbSmPState.devInstances)}\n`;
if (extraDevices) msg += `- Extra Devices: ${formatNumber(extraDevices)} (${formatCurrency(extraDevicesCost)})\n`;
if (extraProd) msg += `- Extra Prod: ${formatNumber(extraProd)} (${formatCurrency(extraProdCost)})\n`;
@@ -571,6 +600,7 @@ Calculation summary
if (!tbSmPUi.openBtn || !tbSmPUi.modal) return;
tbSmPUi.openBtn.addEventListener('click', () => {
+ document.querySelector('header').style.display = 'none';
openModal(tbSmPUi.modal);
setTimeout(tbSmPInitTicks, 50);
@@ -579,18 +609,20 @@ Calculation summary
tbSmPCalculate();
});
- tbSmPUi.closeBtn.addEventListener('click', () => closeModal(tbSmPUi.modal));
- tbSmPUi.modal.addEventListener('click', e => e.target === tbSmPUi.modal && closeModal(tbSmPUi.modal));
+ const perpCloseModal = () => { closeModal(tbSmPUi.modal); document.querySelector('header').style.display = ''; };
+ tbSmPUi.closeBtn.addEventListener('click', perpCloseModal);
+ tbSmPUi.modal.addEventListener('click', e => e.target === tbSmPUi.modal && perpCloseModal());
tbSmPUi.resetBtn.addEventListener('click', () => {
tbSmPState = {
clipboardMessage: '',
debounceTimer: null,
deviceCount: 1000,
+ _prevDevices: 1000,
prodInstances: 1,
devInstances: 0,
addons: {
- edge: { enabled: true, count: 2 },
+ edge: { enabled: false, count: 2 },
trendz: { enabled: false },
offline: { enabled: false }
}
@@ -600,7 +632,7 @@ Calculation summary
tbSmPUi.inputs.prod.value = 1;
tbSmPUi.inputs.dev.value = 0;
tbSmPUi.inputs.edge.value = 2;
- tbSmPUi.toggles.edge.checked = true;
+ tbSmPUi.toggles.edge.checked = false;
tbSmPUi.toggles.trendz.checked = false;
tbSmPUi.toggles.offline.checked = false;
sliderProgress(tbSmPUi.inputs.slider);
@@ -643,9 +675,10 @@ Calculation summary
bindStepper(tbSmPUi.steppers.edge, 'edge');
tbSmPUi.inputs.prod.addEventListener('change', e => {
- tbSmPState.prodInstances = Math.max(tbSmPPlan.includedProdInstances, parseInt(e.target.value) || 1);
+ const min = tbSmPGetMinProd();
+ tbSmPState.prodInstances = Math.max(min, parseInt(e.target.value) || 1);
e.target.value = tbSmPState.prodInstances;
- tbSmPUi.steppers.prod.querySelector('[data-action="decrement"]').disabled = tbSmPState.prodInstances <= tbSmPPlan.includedProdInstances;
+ tbSmPUi.steppers.prod.querySelector('[data-action="decrement"]').disabled = tbSmPState.prodInstances <= min;
tbSmPCalculate();
tbSmPSendGTM();
});
diff --git a/_layouts/pricing.html b/_layouts/pricing.html
index bc716fd190..46cd874678 100644
--- a/_layouts/pricing.html
+++ b/_layouts/pricing.html
@@ -233,6 +233,10 @@
const headerId = $solutionButtonElement.attr("data-description-toggle");
$('.pricing-div .pricing-section'+id).addClass("active");
$('.pricing-content-header .pricing-content-description'+headerId).addClass("active");
+ const header = $solutionButtonElement.closest('.pricing-content').find('.pricing-content-header')[0];
+ if (header) {
+ header.style.marginBottom = (sectionId === 'pe-perpetual' || sectionId === 'tbmq-pe-perpetual') ? '16px' : '';
+ }
switchFaqContainer(sectionId);
}
}
@@ -472,7 +476,7 @@
}
function generateAddOnsCards(currency = 'usd') {
- document.querySelectorAll('.add-ons').forEach(elem => {
+ document.querySelectorAll('.add-ons[data-product-name]').forEach(elem => {
const product = elem.dataset.productName;
const addOnsPricing = {{ addons }};
diff --git a/images/pricing/offline-add-on-icon.svg b/images/pricing/offline-add-on-icon.svg
new file mode 100644
index 0000000000..3deb4d77e8
--- /dev/null
+++ b/images/pricing/offline-add-on-icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/pricing/index.md b/pricing/index.md
index 8c86997ab3..2875180471 100644
--- a/pricing/index.md
+++ b/pricing/index.md
@@ -745,7 +745,7 @@ defaultActivePricingSection: thingsboard-pe-options
Not sure which plan fits?
Use our calculator to estimate the best plan for your needs.
-
+
@@ -871,6 +871,9 @@ defaultActivePricingSection: thingsboard-pe-options
All subscription plans include unlimited customers, dashboards, integrations, api calls, data points & messages.
+
+ License packages
+
Not sure which plan fits?
Use our calculator to estimate the best plan for your needs.
-
+
@@ -1057,18 +1060,23 @@ defaultActivePricingSection: thingsboard-pe-options
Own Your IoT Solution. Perpetually.
- The one-time, enterprise-grade license for maximum security, permanent data control, and predictable costs.
+ The one-time, enterprise-grade license for maximum security, permanent data control, and predictable costs.
A perpetual license transforms your core IoT platform into a permanent asset, giving you a predictable financial model and complete control over your technology roadmap. It's the ideal foundation for a long-term, large-scale enterprise deployment.
+ Starting from $4 999
This solution is for you if:
- Your security policy requires an isolated, on-premises, or offline deployment.
- Your financial model favors a one-time capital investment (CAPEX) over recurring expenses.
- Your business needs a unique, tailored solution, not a one-size-fits-all subscription.
-
- Contact us
- to get your perpetual license
-
+
+
+
+ Contact Us
+
+
Why choose a Perpetual License?
@@ -1091,15 +1099,46 @@ defaultActivePricingSection: thingsboard-pe-options
- Let us help you identify the best option for your business
-
- Contact us
- to get your perpetual license
-
+
Calculation summary
-Calculation summary
+Calculation summary
if (tbSmPState.addons.edge.enabled && breakdown.edge) { const edge = breakdown.edge; const content = `Calculation summary
const trendz = breakdown.trendz; const hasExtra = trendz.extraDevices > 0; const content = hasExtra ? `Calculation summary
html += `Calculation summary
}); }; - const tbSmPUpdateClipboard = ({ plan, devices, extraDevices, extraDevicesCost, extraProd, extraProdCost, devCost, breakdown, totalPrice }) => { + const tbSmPUpdateClipboard = ({ plan, devices, extraDevices, extraDevicesCost, complimentaryProd, extraProd, extraProdCost, devCost, breakdown, totalPrice }) => { let msg = `Perpetual License: ${plan.name} (${formatCurrency(plan.price)})\n`; msg += `- Devices: ${formatNumber(devices)}\n`; - msg += `- Prod Instances: ${formatNumber(tbSmPState.prodInstances)}\n`; + msg += `- Prod Instances: ${formatNumber(tbSmPState.prodInstances)}`; + if (complimentaryProd > 0) msg += ` (${plan.includedProdInstances} included + ${complimentaryProd} complimentary)`; + msg += '\n'; msg += `- Dev Instances: ${formatNumber(tbSmPState.devInstances)}\n`; if (extraDevices) msg += `- Extra Devices: ${formatNumber(extraDevices)} (${formatCurrency(extraDevicesCost)})\n`; if (extraProd) msg += `- Extra Prod: ${formatNumber(extraProd)} (${formatCurrency(extraProdCost)})\n`; @@ -571,6 +600,7 @@Calculation summary
if (!tbSmPUi.openBtn || !tbSmPUi.modal) return; tbSmPUi.openBtn.addEventListener('click', () => { + document.querySelector('header').style.display = 'none'; openModal(tbSmPUi.modal); setTimeout(tbSmPInitTicks, 50); @@ -579,18 +609,20 @@Calculation summary
tbSmPCalculate(); }); - tbSmPUi.closeBtn.addEventListener('click', () => closeModal(tbSmPUi.modal)); - tbSmPUi.modal.addEventListener('click', e => e.target === tbSmPUi.modal && closeModal(tbSmPUi.modal)); + const perpCloseModal = () => { closeModal(tbSmPUi.modal); document.querySelector('header').style.display = ''; }; + tbSmPUi.closeBtn.addEventListener('click', perpCloseModal); + tbSmPUi.modal.addEventListener('click', e => e.target === tbSmPUi.modal && perpCloseModal()); tbSmPUi.resetBtn.addEventListener('click', () => { tbSmPState = { clipboardMessage: '', debounceTimer: null, deviceCount: 1000, + _prevDevices: 1000, prodInstances: 1, devInstances: 0, addons: { - edge: { enabled: true, count: 2 }, + edge: { enabled: false, count: 2 }, trendz: { enabled: false }, offline: { enabled: false } } @@ -600,7 +632,7 @@Calculation summary
tbSmPUi.inputs.prod.value = 1; tbSmPUi.inputs.dev.value = 0; tbSmPUi.inputs.edge.value = 2; - tbSmPUi.toggles.edge.checked = true; + tbSmPUi.toggles.edge.checked = false; tbSmPUi.toggles.trendz.checked = false; tbSmPUi.toggles.offline.checked = false; sliderProgress(tbSmPUi.inputs.slider); @@ -643,9 +675,10 @@Calculation summary
bindStepper(tbSmPUi.steppers.edge, 'edge'); tbSmPUi.inputs.prod.addEventListener('change', e => { - tbSmPState.prodInstances = Math.max(tbSmPPlan.includedProdInstances, parseInt(e.target.value) || 1); + const min = tbSmPGetMinProd(); + tbSmPState.prodInstances = Math.max(min, parseInt(e.target.value) || 1); e.target.value = tbSmPState.prodInstances; - tbSmPUi.steppers.prod.querySelector('[data-action="decrement"]').disabled = tbSmPState.prodInstances <= tbSmPPlan.includedProdInstances; + tbSmPUi.steppers.prod.querySelector('[data-action="decrement"]').disabled = tbSmPState.prodInstances <= min; tbSmPCalculate(); tbSmPSendGTM(); }); diff --git a/_layouts/pricing.html b/_layouts/pricing.html index bc716fd190..46cd874678 100644 --- a/_layouts/pricing.html +++ b/_layouts/pricing.html @@ -233,6 +233,10 @@ const headerId = $solutionButtonElement.attr("data-description-toggle"); $('.pricing-div .pricing-section'+id).addClass("active"); $('.pricing-content-header .pricing-content-description'+headerId).addClass("active"); + const header = $solutionButtonElement.closest('.pricing-content').find('.pricing-content-header')[0]; + if (header) { + header.style.marginBottom = (sectionId === 'pe-perpetual' || sectionId === 'tbmq-pe-perpetual') ? '16px' : ''; + } switchFaqContainer(sectionId); } } @@ -472,7 +476,7 @@ } function generateAddOnsCards(currency = 'usd') { - document.querySelectorAll('.add-ons').forEach(elem => { + document.querySelectorAll('.add-ons[data-product-name]').forEach(elem => { const product = elem.dataset.productName; const addOnsPricing = {{ addons }}; diff --git a/images/pricing/offline-add-on-icon.svg b/images/pricing/offline-add-on-icon.svg new file mode 100644 index 0000000000..3deb4d77e8 --- /dev/null +++ b/images/pricing/offline-add-on-icon.svg @@ -0,0 +1,6 @@ + diff --git a/pricing/index.md b/pricing/index.md index 8c86997ab3..2875180471 100644 --- a/pricing/index.md +++ b/pricing/index.md @@ -745,7 +745,7 @@ defaultActivePricingSection: thingsboard-pe-optionsNot sure which plan fits?
Use our calculator to estimate the best plan for your needs.
License packages
+Use our calculator to estimate the best plan for your needs.
Own Your IoT Solution. Perpetually.
-The one-time, enterprise-grade license for maximum security, permanent data control, and predictable costs.
+The one-time, enterprise-grade license for maximum security, permanent data control, and predictable costs.
A perpetual license transforms your core IoT platform into a permanent asset, giving you a predictable financial model and complete control over your technology roadmap. It's the ideal foundation for a long-term, large-scale enterprise deployment.
+Starting from $4 999
This solution is for you if:
- Your security policy requires an isolated, on-premises, or offline deployment.
- Your financial model favors a one-time capital investment (CAPEX) over recurring expenses.
- Your business needs a unique, tailored solution, not a one-size-fits-all subscription.