api / scripts /create_pptx.py
safraeli's picture
Deploy: 2026 sensor migration + redesign + bucket B endpoints
13fc29d verified
Raw History Blame Contribute Delete
41.3 kB
"""Create a PowerPoint presentation for the solar system electrical plan β€” v2 (Series topology)."""
from pptx import Presentation
from pptx.util import Inches, Pt, Cm, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.oxml.ns import qn
import os
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
# ── Color palette ──
NAVY = RGBColor(0x0C, 0x23, 0x40)
BLUE = RGBColor(0x1A, 0x52, 0x76)
GOLD = RGBColor(0xF0, 0xC0, 0x40)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
LIGHT_BG = RGBColor(0xF5, 0xF6, 0xFA)
RED = RGBColor(0xC6, 0x28, 0x28)
ORANGE = RGBColor(0xE6, 0x51, 0x00)
GREEN = RGBColor(0x2E, 0x7D, 0x32)
TEAL = RGBColor(0x00, 0x89, 0x7B)
DARK_TEXT = RGBColor(0x1A, 0x1A, 0x2E)
GRAY = RGBColor(0x55, 0x55, 0x55)
LIGHT_GOLD = RGBColor(0xFF, 0xF8, 0xE1)
LIGHT_RED = RGBColor(0xFF, 0xEB, 0xEE)
LIGHT_GREEN = RGBColor(0xE8, 0xF5, 0xE9)
LIGHT_BLUE = RGBColor(0xE3, 0xF2, 0xFD)
LIGHT_ORANGE = RGBColor(0xFF, 0xF3, 0xE0)
PURPLE = RGBColor(0x7B, 0x5E, 0xA7)
# ── Helpers ──
def set_slide_bg(slide, color):
bg = slide.background
fill = bg.fill
fill.solid()
fill.fore_color.rgb = color
def add_shape(slide, left, top, width, height, fill_color=None, line_color=None, shape_type=MSO_SHAPE.ROUNDED_RECTANGLE):
shape = slide.shapes.add_shape(shape_type, left, top, width, height)
shape.shadow.inherit = False
if fill_color:
shape.fill.solid()
shape.fill.fore_color.rgb = fill_color
else:
shape.fill.background()
if line_color:
shape.line.color.rgb = line_color
shape.line.width = Pt(1)
else:
shape.line.fill.background()
return shape
def set_text(shape, text, font_size=14, color=DARK_TEXT, bold=False, alignment=PP_ALIGN.RIGHT, font_name='Arial'):
tf = shape.text_frame
tf.word_wrap = True
tf.auto_size = None
p = tf.paragraphs[0]
p.alignment = alignment
run = p.add_run()
run.text = text
run.font.size = Pt(font_size)
run.font.color.rgb = color
run.font.bold = bold
run.font.name = font_name
pPr = p._p.get_or_add_pPr()
pPr.set('rtl', '1')
return tf
def add_text_box(slide, left, top, width, height, text, font_size=14, color=DARK_TEXT, bold=False, alignment=PP_ALIGN.RIGHT):
txBox = slide.shapes.add_textbox(left, top, width, height)
tf = txBox.text_frame
tf.word_wrap = True
p = tf.paragraphs[0]
p.alignment = alignment
pPr = p._p.get_or_add_pPr()
pPr.set('rtl', '1')
run = p.add_run()
run.text = text
run.font.size = Pt(font_size)
run.font.color.rgb = color
run.font.bold = bold
run.font.name = 'Arial'
return tf
def add_multiline_box(slide, left, top, width, height, lines, default_size=13, default_color=DARK_TEXT):
txBox = slide.shapes.add_textbox(left, top, width, height)
tf = txBox.text_frame
tf.word_wrap = True
for i, line_data in enumerate(lines):
text = line_data[0]
size = line_data[1] if len(line_data) > 1 else default_size
color = line_data[2] if len(line_data) > 2 else default_color
bold = line_data[3] if len(line_data) > 3 else False
align = line_data[4] if len(line_data) > 4 else PP_ALIGN.RIGHT
if i == 0:
p = tf.paragraphs[0]
else:
p = tf.add_paragraph()
p.alignment = align
pPr = p._p.get_or_add_pPr()
pPr.set('rtl', '1')
p.space_after = Pt(4)
run = p.add_run()
run.text = text
run.font.size = Pt(size)
run.font.color.rgb = color
run.font.bold = bold
run.font.name = 'Arial'
return tf
def add_table_slide(slide, left, top, width, row_height, headers, rows, header_bg=NAVY, header_fg=WHITE, highlight_rows=None, col_ratios=None):
num_rows = len(rows) + 1
num_cols = len(headers)
table_shape = slide.shapes.add_table(num_rows, num_cols, left, top, width, Pt(row_height * num_rows))
table = table_shape.table
if col_ratios:
total = sum(col_ratios)
for i, ratio in enumerate(col_ratios):
table.columns[i].width = int(width * ratio / total)
else:
col_width = int(width / num_cols)
for i in range(num_cols):
table.columns[i].width = col_width
for i, h in enumerate(headers):
cell = table.cell(0, i)
cell.text = h
cell.fill.solid()
cell.fill.fore_color.rgb = header_bg
for p in cell.text_frame.paragraphs:
p.alignment = PP_ALIGN.RIGHT
pPr = p._p.get_or_add_pPr()
pPr.set('rtl', '1')
for run in p.runs:
run.font.size = Pt(12)
run.font.color.rgb = header_fg
run.font.bold = True
run.font.name = 'Arial'
for r_idx, row in enumerate(rows):
for c_idx, val in enumerate(row):
cell = table.cell(r_idx + 1, c_idx)
cell.text = str(val)
if highlight_rows and r_idx in highlight_rows:
cell.fill.solid()
cell.fill.fore_color.rgb = LIGHT_GOLD
for p in cell.text_frame.paragraphs:
p.alignment = PP_ALIGN.RIGHT
pPr = p._p.get_or_add_pPr()
pPr.set('rtl', '1')
for run in p.runs:
run.font.size = Pt(11)
run.font.color.rgb = DARK_TEXT
run.font.name = 'Arial'
return table
def add_card(slide, left, top, width, height, title, body_lines, fill=WHITE, accent=GOLD):
bar = add_shape(slide, left, top, width, Pt(4), fill_color=accent, shape_type=MSO_SHAPE.RECTANGLE)
card = add_shape(slide, left, top + Pt(4), width, height - Pt(4), fill_color=fill, line_color=RGBColor(0xE0, 0xE4, 0xEA))
add_text_box(slide, left + Pt(10), top + Pt(10), width - Pt(20), Pt(24), title, font_size=15, color=NAVY, bold=True)
add_multiline_box(slide, left + Pt(10), top + Pt(36), width - Pt(20), height - Pt(46), body_lines, default_size=11)
def section_header(slide, text, y=Inches(0.3)):
add_text_box(slide, Inches(0.5), y, Inches(12), Inches(0.7), text, font_size=28, color=NAVY, bold=True)
add_shape(slide, Inches(0.5), y + Inches(0.65), Inches(2), Pt(3), fill_color=GOLD, shape_type=MSO_SHAPE.RECTANGLE)
def add_block(slide, x, y, w, h, text, sub, fill, text_color=WHITE, sub_color=None):
shape = add_shape(slide, x, y, w, h, fill_color=fill)
tf = shape.text_frame
tf.word_wrap = True
tf.paragraphs[0].alignment = PP_ALIGN.CENTER
pPr = tf.paragraphs[0]._p.get_or_add_pPr()
pPr.set('rtl', '1')
run = tf.paragraphs[0].add_run()
run.text = text
run.font.size = Pt(12)
run.font.color.rgb = text_color
run.font.bold = True
run.font.name = 'Arial'
if sub:
p2 = tf.add_paragraph()
p2.alignment = PP_ALIGN.CENTER
pPr2 = p2._p.get_or_add_pPr()
pPr2.set('rtl', '1')
run2 = p2.add_run()
run2.text = sub
run2.font.size = Pt(9)
run2.font.color.rgb = sub_color or RGBColor(0xCC, 0xCC, 0xCC)
run2.font.name = 'Arial'
def add_checklist_col(slide, x_start, y_start, items):
"""items = list of (task, detail)"""
y = y_start
for task, detail in items:
add_text_box(slide, x_start, y, Inches(5.5), Inches(0.2), task, font_size=11, color=DARK_TEXT, bold=True)
add_text_box(slide, x_start, y + Pt(14), Inches(5.5), Inches(0.15), detail, font_size=9, color=GRAY)
y += Inches(0.4)
# ═══════════════════════════════════════════════════════════
# SLIDE 1 β€” Title
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, NAVY)
add_shape(slide, Inches(1), Inches(3.1), Inches(2), Pt(3), fill_color=GOLD, shape_type=MSO_SHAPE.RECTANGLE)
add_text_box(slide, Inches(1), Inches(1.2), Inches(11), Inches(1.5),
'ΧͺΧ›Χ Χ™Χͺ Χ—Χ©ΧžΧœΧ™Χͺ β€” ΧžΧ’Χ¨Χ›Χͺ Χ‘Χ•ΧœΧΧ¨Χ™Χͺ Χ”Χ™Χ‘Χ¨Χ™Χ“Χ™Χͺ', font_size=40, color=WHITE, bold=True)
add_text_box(slide, Inches(1), Inches(2.4), Inches(11), Inches(0.6),
'Χ—Χ•Χ•Χͺ יאיר β€” ΧΧœΧ™ ב׀רא', font_size=24, color=RGBColor(0xA8, 0xD8, 0xEA))
meta_items = [
'מרΧ₯ 2026',
'ΧžΧžΧ™Χ¨: Solis S6-EH3P20K-H | 20kW ΧͺלΧͺ-׀אזי',
'Χ‘Χ•ΧœΧœΧ”: CNTE 18.8kWh HV | LiFePO4',
'Χ€ΧΧ ΧœΧ™Χ: 18 x 620W = 11.16kWp',
'Zero Export | Χ˜Χ•Χ€Χ•ΧœΧ•Χ’Χ™Χ” Χ‘Χ“Χ¨ΧͺΧ™Χͺ | ללא CT',
]
add_multiline_box(slide, Inches(1), Inches(3.5), Inches(11), Inches(2.5),
[(m, 16, RGBColor(0xCD, 0xDE, 0xEE)) for m in meta_items])
# Bottom bar
add_shape(slide, Inches(0), Inches(7.1), Inches(13.333), Pt(30), fill_color=GOLD, shape_type=MSO_SHAPE.RECTANGLE)
add_text_box(slide, Inches(1), Inches(7.12), Inches(11), Pt(26),
'ΧͺΧ›Χ Χ•ΧŸ Χ‘ΧœΧ‘Χ“ β€” ΧœΧΧ™Χ©Χ•Χ¨ Χ—Χ©ΧžΧœΧΧ™ ΧžΧ•Χ‘ΧžΧš ΧœΧ€Χ Χ™ Χ‘Χ™Χ¦Χ•Χ’', font_size=12, color=NAVY, bold=True, alignment=PP_ALIGN.CENTER)
# ═══════════════════════════════════════════════════════════
# SLIDE 2 β€” Notes (replacing Critical Warnings)
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
add_text_box(slide, Inches(0.5), Inches(0.3), Inches(12), Inches(0.7),
'Χ”Χ’Χ¨Χ•Χͺ Χ—Χ©Χ•Χ‘Χ•Χͺ ΧœΧ€Χ Χ™ Χ‘Χ™Χ¦Χ•Χ’', font_size=28, color=ORANGE, bold=True)
add_shape(slide, Inches(0.5), Inches(0.95), Inches(2), Pt(3), fill_color=ORANGE, shape_type=MSO_SHAPE.RECTANGLE)
notes = [
('Χ˜Χ•Χ€Χ•ΧœΧ•Χ’Χ™Χ” Χ‘Χ“Χ¨ΧͺΧ™Χͺ (Series)',
'Χ›Χœ Χ”Χ—Χ©ΧžΧœ Χ’Χ•Χ‘Χ¨ Χ“Χ¨Χš Χ”ΧžΧžΧ™Χ¨. ΧΧ™ΧŸ CT. ΧΧ™ΧŸ DC Isolators חיצוניים\n(ΧžΧ•Χ‘Χ Χ™Χ Χ‘ΧžΧžΧ™Χ¨ Χ•Χ‘Χ‘Χ•ΧœΧœΧ”). ΧžΧ€Χ‘Χ§Χ™ C40 ΧžΧ‘Χ€Χ™Χ§Χ™Χ.',
'הוודא גל Χ™Χ“Χ™ Χ”ΧžΧͺΧ§Χ™ΧŸ'),
('RCD (Χ€Χ—Χͺ)',
'לא Χ Χ›ΧœΧœ Χ›Χ¨Χ’Χ’ β€” Χ™Χ™Χ§Χ‘Χ’ ΧœΧ€Χ™ Χ“Χ¨Χ™Χ©Χͺ Χ”Χ‘Χ•Χ“Χ§ Χ‘Χ”Χͺאם ΧœΧžΧ“Χ“Χ™ הארקה.\nΧžΧ•ΧžΧœΧ₯ ΧœΧ©Χ§Χ•Χœ Χ”Χ•Χ‘Χ€Χ” מראש ΧœΧ‘Χ˜Χ™Χ—Χ•Χͺ.',
'Χ Χ“Χ—Χ” ΧœΧ©ΧœΧ‘ Χ‘Χ“Χ™Χ§Χ”'),
('Χ˜Χ‘Χ’Χͺ ΧžΧ’Χ Χ˜Χ™Χͺ ΧœΧ›Χ‘Χœ Χ‘Χ•ΧœΧœΧ”',
'ΧœΧ€Χ™ Χ”ΧžΧͺΧ§Χ™ΧŸ, Χ›Χ‘Χœ Χ”Χ‘Χ•ΧœΧœΧ” Χ§Χ¦Χ¨ ΧžΧ“Χ™ לל׀ף.\nΧ Χ§Χ•Χ“Χ” Χ€ΧͺΧ•Χ—Χ” β€” ΧœΧ‘Χ¨Χ¨ אם CNTE Χ›Χ•ΧœΧœ ferrite ΧžΧ•Χ‘Χ Χ”, או ΧœΧ”Χ©Χͺמש Χ‘Χ›Χ‘Χœ ΧΧ¨Χ•Χš Χ™Χ•ΧͺΧ¨.',
'Χ Χ§Χ•Χ“Χ” Χ€ΧͺΧ•Χ—Χ”'),
]
y = Inches(1.3)
for title, desc, status in notes:
card = add_shape(slide, Inches(0.5), y, Inches(12), Inches(1.4), fill_color=WHITE, line_color=RGBColor(0xE0, 0xA0, 0x00))
add_shape(slide, Inches(0.5), y, Pt(6), Inches(1.4), fill_color=ORANGE, shape_type=MSO_SHAPE.RECTANGLE)
add_text_box(slide, Inches(0.8), y + Pt(8), Inches(9), Pt(24), title, font_size=16, color=ORANGE, bold=True)
add_text_box(slide, Inches(0.8), y + Pt(34), Inches(9), Pt(60), desc, font_size=12, color=GRAY)
# Status badge on the right
badge = add_shape(slide, Inches(10), y + Pt(14), Inches(2.2), Inches(0.35), fill_color=LIGHT_GOLD)
set_text(badge, status, font_size=11, color=ORANGE, bold=True, alignment=PP_ALIGN.CENTER)
y += Inches(1.6)
# Key info box
box = add_shape(slide, Inches(0.5), Inches(6), Inches(12), Inches(0.8), fill_color=LIGHT_GREEN)
add_multiline_box(slide, Inches(0.7), Inches(6.05), Inches(11.6), Inches(0.7), [
('שינויים גיקריים ΧžΧ’Χ¨Χ‘Χ” Χ§Χ•Χ“ΧžΧͺ: ללא DC Isolators חיצוניים (ΧžΧ•Χ‘Χ Χ™Χ) | ללא CT (series topology) | C40 ΧžΧ‘Χ€Χ™Χ§ (לא C50) | Zero Export ΧΧ•Χ˜Χ•ΧžΧ˜Χ™ | 3P אחרי Χ‘Χ•Χ¨Χ¨ ΧžΧ¦Χ‘Χ™Χ', 12, GREEN, True, PP_ALIGN.CENTER),
])
# ═══════════════════════════════════════════════════════════
# SLIDE 3 β€” Single Line Diagram
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '1. Χͺרשים Χ—Χ“-Χ§Χ•Χ•Χ™ (Single Line Diagram)')
# Series topology banner
banner = add_shape(slide, Inches(0.5), Inches(1.1), Inches(12.3), Inches(0.4), fill_color=LIGHT_GREEN)
add_text_box(slide, Inches(0.7), Inches(1.12), Inches(12), Inches(0.35),
'Χ˜Χ•Χ€Χ•ΧœΧ•Χ’Χ™Χ” Χ‘Χ“Χ¨ΧͺΧ™Χͺ β€” Χ›Χœ Χ”Χ—Χ©ΧžΧœ Χ’Χ•Χ‘Χ¨ Χ“Χ¨Χš Χ”ΧžΧžΧ™Χ¨ | Zero Export | ללא CT',
font_size=13, color=GREEN, bold=True, alignment=PP_ALIGN.CENTER)
LINE_W = Pt(2.5)
def add_line_h(slide, x, y, length, color):
"""Horizontal line (thin rectangle)."""
add_shape(slide, x, y, length, LINE_W, fill_color=color, shape_type=MSO_SHAPE.RECTANGLE)
def add_line_v(slide, x, y, length, color):
"""Vertical line (thin rectangle)."""
add_shape(slide, x, y, LINE_W, length, fill_color=color, shape_type=MSO_SHAPE.RECTANGLE)
DC_PV_COLOR = RGBColor(0xF0, 0xC0, 0x40)
DC_BATT_COLOR = TEAL
AC_GRID_COLOR = RGBColor(0x15, 0x65, 0xC0)
AC_BACKUP_COLOR = ORANGE
AC_DIST_COLOR = RGBColor(0x45, 0x5A, 0x64)
BMS_COLOR = RGBColor(0x26, 0xA6, 0x9A)
# ── Block positions (all in inches, stored for line drawing) ──
# PV Strings
s1_x, s1_y, s1_w, s1_h = 2.0, 1.7, 2.5, 0.65
s2_x, s2_y, s2_w, s2_h = 8.5, 1.7, 2.5, 0.65
# Inverter
inv_x, inv_y, inv_w, inv_h = 4.5, 2.85, 4.2, 0.9
# Battery
bat_x, bat_y, bat_w, bat_h = 0.5, 2.95, 2.3, 0.8
# SPD
spd_x, spd_y, spd_w, spd_h = 5.1, 4.1, 1.8, 0.5
# MCB
mcb_x, mcb_y, mcb_w, mcb_h = 7.2, 4.1, 1.5, 0.5
# Changeover
chg_x, chg_y, chg_w, chg_h = 5.4, 4.85, 2.5, 0.55
# Grid
grid_x, grid_y, grid_w, grid_h = 2.5, 5.75, 2.0, 0.55
# Load
load_x, load_y, load_w, load_h = 8.5, 5.75, 2.0, 0.55
# Backup
bkp_x, bkp_y, bkp_w, bkp_h = 10.5, 2.95, 2.2, 0.8
# ── Draw blocks ──
str_w_in = Inches(s1_w)
add_block(slide, Inches(s1_x), Inches(s1_y), str_w_in, Inches(s1_h),
'String 1: 9x620W = 5,580Wp', 'Vocβ‰ˆ396V | Iscβ‰ˆ18A | MPPT1',
DC_PV_COLOR, DARK_TEXT, GRAY)
add_block(slide, Inches(s2_x), Inches(s2_y), str_w_in, Inches(s2_h),
'String 2: 9x620W = 5,580Wp', 'Vocβ‰ˆ396V | Iscβ‰ˆ18A | MPPT2',
DC_PV_COLOR, DARK_TEXT, GRAY)
add_text_box(slide, Inches(4.5), Inches(2.45), Inches(4), Inches(0.25),
'DC switch ΧžΧ•Χ‘Χ Χ” Χ‘ΧžΧžΧ™Χ¨ β€” ללא DC Isolator Χ—Χ™Χ¦Χ•Χ Χ™',
font_size=10, color=GRAY, alignment=PP_ALIGN.CENTER)
add_block(slide, Inches(inv_x), Inches(inv_y), Inches(inv_w), Inches(inv_h),
'Solis S6-EH3P20K-H', 'Hybrid 20kW | 3Ο† | IP66 | Series | DC switch + AFCI ΧžΧ•Χ‘Χ Χ™Χ',
NAVY, WHITE, RGBColor(0xA8, 0xD8, 0xEA))
add_block(slide, Inches(bat_x), Inches(bat_y), Inches(bat_w), Inches(bat_h),
'CNTE 18.8kWh', 'HV | LFP | IP66 | DC switch ΧžΧ•Χ‘Χ Χ”',
RGBColor(0xE0, 0xF2, 0xF1), DARK_TEXT, GRAY)
add_block(slide, Inches(spd_x), Inches(spd_y), Inches(spd_w), Inches(spd_h),
'SPD Type 2', '3P+N | 40kA',
LIGHT_RED, RED, GRAY)
add_block(slide, Inches(mcb_x), Inches(mcb_y), Inches(mcb_w), Inches(mcb_h),
'MCB C40 4P', 'יציאΧͺ ΧžΧžΧ™Χ¨',
RGBColor(0xED, 0xE7, 0xF6), DARK_TEXT, GRAY)
add_block(slide, Inches(chg_x), Inches(chg_y), Inches(chg_w), Inches(chg_h),
'Χ‘Χ•Χ¨Χ¨ ΧžΧ¦Χ‘Χ™Χ Hager 4P 40A', 'Grid / Solar / Off',
RGBColor(0xF3, 0xE5, 0xF5), DARK_TEXT, GRAY)
add_block(slide, Inches(grid_x), Inches(grid_y), Inches(grid_w), Inches(grid_h),
'MCB C40 3P β†’ ΧžΧ•Χ Χ” Χ™Χ™Χ©Χ•Χ‘', 'Χ¨Χ©Χͺ Χ—Χ©ΧžΧœ',
RGBColor(0xEC, 0xEF, 0xF1), DARK_TEXT, GRAY)
add_block(slide, Inches(load_x), Inches(load_y), Inches(load_w), Inches(load_h),
'MCB C40 3P β†’ ΧœΧ•Χ— Χ—Χ©ΧžΧœΧ™', 'Χ’Χ•ΧžΧ‘Χ™ Χ”Χ‘Χ™Χͺ',
LIGHT_GREEN, DARK_TEXT, GRAY)
add_block(slide, Inches(bkp_x), Inches(bkp_y), Inches(bkp_w), Inches(bkp_h),
'Χ’Χ•ΧžΧ‘Χ™Χ חיוניים', 'Backup UPS <10ms | C40 3P',
LIGHT_ORANGE, DARK_TEXT, GRAY)
# ── Draw connecting lines ──
# String 1 bottom center β†’ down to merge line
s1_cx = s1_x + s1_w / 2 # 3.25
s1_bot = s1_y + s1_h # 2.35
add_line_v(slide, Inches(s1_cx), Inches(s1_bot), Inches(0.25), DC_PV_COLOR)
# String 2 bottom center β†’ down to merge line
s2_cx = s2_x + s2_w / 2 # 9.75
s2_bot = s2_y + s2_h # 2.35
add_line_v(slide, Inches(s2_cx), Inches(s2_bot), Inches(0.25), DC_PV_COLOR)
# Horizontal merge line between String 1 and String 2 at y=2.6
merge_y = 2.6
add_line_h(slide, Inches(s1_cx), Inches(merge_y), Inches(s2_cx - s1_cx), DC_PV_COLOR)
# Center of merge β†’ down to inverter top
inv_cx = inv_x + inv_w / 2 # 6.6
add_line_v(slide, Inches(inv_cx), Inches(merge_y), Inches(inv_y - merge_y), DC_PV_COLOR)
# Battery right edge β†’ horizontal to inverter left edge (DC HV)
bat_right = bat_x + bat_w # 2.8
bat_cy = bat_y + bat_h / 2 # 3.35
add_line_h(slide, Inches(bat_right), Inches(bat_cy), Inches(inv_x - bat_right), DC_BATT_COLOR)
# BMS label
add_text_box(slide, Inches(3.0), Inches(3.05), Inches(1.3), Inches(0.2),
'DC HV + CAN/BMS', font_size=9, color=BMS_COLOR, alignment=PP_ALIGN.CENTER)
# ── AC path: Inverter β†’ SPD β†’ MCB β†’ Changeover ──
inv_bot = inv_y + inv_h # 3.75
spd_cx = spd_x + spd_w / 2 # 6.0
spd_cy = spd_y + spd_h / 2 # 4.35
spd_right = spd_x + spd_w # 6.9
mcb_cx = mcb_x + mcb_w / 2 # 7.95
mcb_bot = mcb_y + mcb_h # 4.6
chg_cx = chg_x + chg_w / 2 # 6.65
chg_top = chg_y # 4.85
# 1. Inv center (6.60) down short
elbow_y = inv_bot + 0.08 # 3.83
add_line_v(slide, Inches(inv_cx), Inches(inv_bot), Inches(elbow_y - inv_bot), AC_GRID_COLOR)
# 2. Horizontal jog from inv_cx (6.60) to spd_cx (6.00)
add_line_h(slide, Inches(spd_cx), Inches(elbow_y), Inches(inv_cx - spd_cx), AC_GRID_COLOR)
# 3. Down from spd_cx to SPD top (6.00, 4.10)
add_line_v(slide, Inches(spd_cx), Inches(elbow_y), Inches(spd_y - elbow_y), AC_GRID_COLOR)
# 4. SPD right β†’ MCB left
add_line_h(slide, Inches(spd_right), Inches(spd_cy), Inches(mcb_x - spd_right), AC_GRID_COLOR)
# 5. MCB bottom center β†’ down
elbow2_y = mcb_bot + 0.05 # 4.65
add_line_v(slide, Inches(mcb_cx), Inches(mcb_bot), Inches(elbow2_y - mcb_bot), AC_GRID_COLOR)
# 6. Horizontal from mcb_cx to chg_cx
add_line_h(slide, Inches(chg_cx), Inches(elbow2_y), Inches(mcb_cx - chg_cx), AC_GRID_COLOR)
# 7. Down from chg_cx to changeover top
add_line_v(slide, Inches(chg_cx), Inches(elbow2_y), Inches(chg_top - elbow2_y), AC_GRID_COLOR)
# Changeover bottom β†’ down then split left/right
chg_bot = chg_y + chg_h # 5.4
branch_y = 5.55
add_line_v(slide, Inches(chg_cx), Inches(chg_bot), Inches(branch_y - chg_bot), AC_DIST_COLOR)
# Horizontal branch line
grid_cx = grid_x + grid_w / 2 # 3.5
load_cx = load_x + load_w / 2 # 9.5
add_line_h(slide, Inches(grid_cx), Inches(branch_y), Inches(load_cx - grid_cx), AC_DIST_COLOR)
# Grid branch: down from branch line to grid block
add_line_v(slide, Inches(grid_cx), Inches(branch_y), Inches(grid_y - branch_y), AC_DIST_COLOR)
# Load branch: down from branch line to load block
add_line_v(slide, Inches(load_cx), Inches(branch_y), Inches(load_y - branch_y), AC_DIST_COLOR)
# Backup: Inverter right β†’ horizontal to backup block left
inv_right = inv_x + inv_w # 8.7
inv_cy = inv_y + inv_h / 2 # 3.3
bkp_left = bkp_x # 10.5
bkp_cy = bkp_y + bkp_h / 2 # 3.35
# Horizontal line
add_line_h(slide, Inches(inv_right), Inches(inv_cy), Inches(bkp_left - inv_right), AC_BACKUP_COLOR)
# Backup label
add_text_box(slide, Inches(inv_right + 0.1), Inches(inv_cy - 0.25), Inches(1.5), Inches(0.2),
'Backup AC | UPS <10ms', font_size=9, color=AC_BACKUP_COLOR, alignment=PP_ALIGN.CENTER)
# ── Legend with colored line samples ──
legend_y = Inches(6.55)
legend_items = [
(0.5, DC_PV_COLOR, 'DC PV'),
(2.2, DC_BATT_COLOR, 'DC Battery'),
(4.2, AC_GRID_COLOR, 'AC Grid'),
(6.0, AC_BACKUP_COLOR, 'AC Backup'),
(8.0, AC_DIST_COLOR, 'Distribution'),
(10.2, BMS_COLOR, 'BMS'),
]
legend_bg = add_shape(slide, Inches(0.3), legend_y - Pt(4), Inches(12.7), Inches(0.4), fill_color=RGBColor(0xF5, 0xF5, 0xF5), line_color=RGBColor(0xE0, 0xE0, 0xE0))
for lx, lcolor, ltext in legend_items:
add_shape(slide, Inches(lx), legend_y + Pt(4), Inches(0.4), Pt(3), fill_color=lcolor, shape_type=MSO_SHAPE.RECTANGLE)
add_text_box(slide, Inches(lx + 0.45), legend_y - Pt(2), Inches(1.3), Inches(0.3),
ltext, font_size=10, color=GRAY, alignment=PP_ALIGN.LEFT)
# ═══════════════════════════════════════════════════════════
# SLIDE 4 β€” Component List (10 items)
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '2. Χ¨Χ©Χ™ΧžΧͺ רכיבים ΧžΧ€Χ•Χ¨Χ˜Χͺ')
components = [
('1', 'Χ€ΧΧ ΧœΧ™Χ Χ‘Χ•ΧœΧΧ¨Χ™Χ™Χ', '620W β€” מק"ט s620', '18', 'Χ’Χ’', '2 Χ‘Χ˜Χ¨Χ™Χ Χ’Χ™Χ x 9. DC switch ΧžΧ•Χ‘Χ Χ” Χ‘ΧžΧžΧ™Χ¨'),
('2', 'ΧžΧžΧ™Χ¨ Χ”Χ™Χ‘Χ¨Χ™Χ“Χ™', 'Solis S6-EH3P20K-H', '1', 'Χ§Χ™Χ¨ ΧžΧ•Χ¦Χœ', 'IP66. DC switch + AFCI ΧžΧ•Χ‘Χ Χ™Χ'),
('3', 'Χ‘Χ•ΧœΧœΧ”', 'CNTE 18.8kWh HV', '1', 'ΧœΧ™Χ“ Χ”ΧžΧžΧ™Χ¨', 'IP66. DC switch ΧžΧ•Χ‘Χ Χ”. CAN'),
('4', 'ΧžΧ’ΧŸ ברקים SPD', 'Type 2, 3P+N, 40kA', '1', 'יציאΧͺ AC ΧžΧžΧ™Χ¨', 'Χ”Χ’Χ Χͺ AC'),
('5', 'מ׀בק יציאΧͺ ΧžΧžΧ™Χ¨', 'ABB C40 4P', '1', 'אחרי SPD', '4P β€” Χ›Χ•ΧœΧœ Χ Χ™Χ™Χ˜Χ¨Χœ'),
('6', 'Χ‘Χ•Χ¨Χ¨ ΧžΧ¦Χ‘Χ™Χ', 'Hager 4P 40A', '1', 'ΧœΧ€Χ Χ™ Χ”ΧͺΧ€Χ¦ΧœΧ•Χͺ', 'Grid / Solar / Off'),
('7', 'מ׀בק Χ¨Χ©Χͺ', 'ABB C40 3P', '1', 'Χ’Χ Χ£ Χ¨Χ©Χͺ', '3P β€” אחרי Χ‘Χ•Χ¨Χ¨'),
('8', 'מ׀בק Χ’Χ•ΧžΧ‘Χ™Χ', 'ABB C40 3P', '1', 'Χ’Χ Χ£ Χ’Χ•ΧžΧ‘Χ™Χ', '3P β€” אחרי Χ‘Χ•Χ¨Χ¨'),
('9', 'מ׀בק Χ’Χ™Χ‘Χ•Χ™', 'ABB C40 3P', '1', 'Backup ΧžΧžΧ™Χ¨', '3P β€” Χ’Χ•ΧžΧ‘Χ™Χ חיוניים'),
('10', 'ΧžΧ•Χ Χ” Χ™Χ™Χ©Χ•Χ‘', 'Χ“Χ•-Χ›Χ™Χ•Χ•Χ Χ™', '1', 'ΧœΧ€Χ Χ™ Χ”Χ¨Χ©Χͺ', 'ΧžΧ‘Χ•Χ€Χ§ Χ’"Χ™ Χ™Χ™Χ©Χ•Χ‘'),
]
add_table_slide(slide, Inches(0.3), Inches(1.2), Inches(12.7), 30,
['#', 'Χ¨Χ›Χ™Χ‘', 'דגם / מ׀רט', 'Χ›ΧžΧ•Χͺ', 'ΧžΧ™Χ§Χ•Χ', 'Χ”Χ’Χ¨Χ•Χͺ'],
components, highlight_rows=[3],
col_ratios=[0.5, 2, 2.5, 0.7, 1.5, 3])
# Note about what's NOT in the list
note = add_shape(slide, Inches(0.3), Inches(5.8), Inches(12.7), Inches(0.7), fill_color=LIGHT_BLUE)
add_multiline_box(slide, Inches(0.5), Inches(5.85), Inches(12.3), Inches(0.6), [
('לא נדרשים: DC Isolators חיצוניים (ΧžΧ•Χ‘Χ Χ™Χ Χ‘ΧžΧžΧ™Χ¨ Χ•Χ‘Χ‘Χ•ΧœΧœΧ”) | CT Χ—Χ™Χ™Χ©ΧŸ זרם (Series topology = Zero Export ΧΧ•Χ˜Χ•ΧžΧ˜Χ™) | C50 (C40 ΧžΧ‘Χ€Χ™Χ§)', 12, BLUE, True, PP_ALIGN.CENTER),
])
# ═══════════════════════════════════════════════════════════
# SLIDE 5 β€” Cable Specifications
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '3. מ׀רט Χ›Χ‘Χ™ΧœΧ”')
cables = [
('PV String β†’ Inverter', 'H1Z2Z2-K Χ‘Χ•ΧœΧΧ¨Χ™', '6mmΒ²', 'ΧœΧ€Χ™ ΧžΧ™Χ§Χ•Χ Χ’Χ’', 'Χ™Χ©Χ™Χ¨Χ•Χͺ ΧœΧžΧžΧ™Χ¨, MC4, UV-resistant'),
('Inverter ↔ Battery', 'DC Χ’ΧžΧ™Χ©', '16mmΒ²', '~3m', 'ΧžΧ’Χ™Χ’ גם Χ”Χ¦Χ™Χ•Χ“. ⚠ ferrite β€” Χ Χ§Χ•Χ“Χ” Χ€ΧͺΧ•Χ—Χ”'),
('Inverter β†’ SPD β†’ MCB', 'NYY-J 5G AC', '10mmΒ²', '~5m', '3L + N + PE'),
('MCB β†’ Switch β†’ Grid/Load', 'NYY-J 5G AC', '10mmΒ²', '~10m', 'ΧœΧ€Χ™ ΧžΧ¨Χ—Χ§ ΧœΧœΧ•Χ—'),
('Backup β†’ MCB β†’ Essential', 'NYY-J 5G AC', '6mmΒ²', '~8m', '3P Χ’Χ•ΧžΧ‘Χ™Χ חיוניים'),
('הארקה', 'Χ™Χ¨Χ•Χ§-Χ¦Χ”Χ•Χ‘', '16mmΒ² Χ Χ—Χ•Χ©Χͺ', 'β€”', 'ΧžΧžΧ™Χ¨+Χ‘Χ•ΧœΧœΧ”+ΧžΧ‘Χ Χ”'),
('BMS Communication', 'CAN ΧžΧ‘Χ•Χ›Χš', 'Χ©Χ–Χ•Χ¨', '~3m', 'ΧžΧ’Χ™Χ’ ΧžΧœΧ•Χ€Χ£ מראש Χ‘Χ˜Χ‘Χ’Χͺ ΧžΧ’Χ Χ˜Χ™Χͺ'),
]
add_table_slide(slide, Inches(0.5), Inches(1.2), Inches(12.3), 30,
['קטג', 'Χ‘Χ•Χ’ Χ›Χ‘Χœ', 'Χ—Χͺך', 'ΧΧ•Χ¨Χš', 'Χ”Χ’Χ¨Χ•Χͺ'],
cables, highlight_rows=[1],
col_ratios=[2.5, 2, 1.2, 1, 3.5])
# Ferrite note
note = add_shape(slide, Inches(0.5), Inches(4.5), Inches(12.3), Inches(0.9), fill_color=LIGHT_GOLD)
add_multiline_box(slide, Inches(0.7), Inches(4.55), Inches(12), Inches(0.8), [
('Χ˜Χ‘Χ’Χ•Χͺ ΧžΧ’Χ Χ˜Χ™Χ•Χͺ (Ferrite Rings):', 13, ORANGE, True),
('Χ›Χ‘Χœ CAN β€” ΧžΧ’Χ™Χ’ ΧžΧœΧ•Χ€Χ£ מראש (ΧœΧ€Χ™ Χ”ΧžΧͺΧ§Χ™ΧŸ)', 12, DARK_TEXT),
('Χ›Χ‘Χœ DC Χ‘Χ•ΧœΧœΧ” β€” Χ”ΧžΧͺΧ§Χ™ΧŸ ΧžΧ¦Χ™Χ™ΧŸ שהוא Χ§Χ¦Χ¨ ΧžΧ“Χ™ לל׀ף. Χ Χ§Χ•Χ“Χ” Χ€ΧͺΧ•Χ—Χ” β€” ΧœΧ‘Χ¨Χ¨ ΧžΧ•Χœ CNTE אם Χ™Χ© ferrite ΧžΧ•Χ‘Χ Χ”, או לב׀ק Χ›Χ‘Χœ ΧΧ¨Χ•Χš Χ™Χ•ΧͺΧ¨', 12, ORANGE, True),
])
# ═══════════════════════════════════════════════════════════
# SLIDE 6 β€” Installation Guidelines
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '4. Χ”Χ Χ—Χ™Χ•Χͺ Χ”ΧͺΧ§Χ Χ”')
card_w = Inches(5.9)
card_h = Inches(2.5)
add_card(slide, Inches(0.5), Inches(1.2), card_w, card_h,
'ΧžΧ™Χ§Χ•Χ ΧžΧžΧ™Χ¨ Χ•Χ‘Χ•ΧœΧœΧ”', [
('β€’ Χ§Χ™Χ¨ ΧžΧ•Χ¦Χœ β€” Χ”Χ’Χ Χ” משמש Χ™Χ©Χ™Χ¨Χ”', 12, DARK_TEXT),
('β€’ Χ’Χ•Χ‘Χ” ΧžΧ™Χ Χ™ΧžΧœΧ™ 60 Χ‘"מ ΧžΧ”Χ§Χ¨Χ§Χ’', 12, DARK_TEXT),
('β€’ ΧžΧ¨Χ•Χ•Χ— אוורור: 30 Χ‘"מ ΧžΧ¦Χ“Χ“Χ™Χ, 50 Χ‘"מ ΧžΧœΧžΧ’ΧœΧ”', 12, DARK_TEXT),
('β€’ Χ Χ’Χ™Χ© לΧͺΧ—Χ–Χ•Χ§Χ”', 12, DARK_TEXT),
('β€’ IP66 β€” מΧͺאים ΧœΧ—Χ•Χ₯', 12, GREEN),
], accent=BLUE)
add_card(slide, Inches(6.8), Inches(1.2), card_w, card_h,
'הארקה', [
('β€’ Χ’Χ•Χ£ ΧžΧžΧ™Χ¨ + Χ’Χ•Χ£ Χ‘Χ•ΧœΧœΧ”', 12, DARK_TEXT),
('β€’ ΧžΧ‘Χ Χ” Χ§Χ•Χ Χ‘Χ˜Χ¨Χ•Χ§Χ¦Χ™Χ”', 12, DARK_TEXT),
('β€’ ΧžΧ‘Χ’Χ¨Χ•Χͺ Χ€ΧΧ ΧœΧ™Χ', 12, DARK_TEXT),
('β€’ Χ—Χͺך ΧžΧ™Χ Χ™ΧžΧœΧ™: 16mmΒ² Χ Χ—Χ•Χ©Χͺ', 12, DARK_TEXT),
('β€’ Χ€Χ‘ הארקה β†’ ΧΧœΧ§Χ˜Χ¨Χ•Χ“Χ”', 12, DARK_TEXT),
], accent=GREEN)
add_card(slide, Inches(0.5), Inches(4.0), card_w, card_h,
'Χ—Χ™Χ‘Χ•Χ¨ Χ‘Χ•ΧœΧœΧ”', [
('β€’ Χ›Χ‘Χœ DC + Χ›Χ‘Χœ CAN ΧžΧ’Χ™Χ’Χ™Χ גם Χ”Χ¦Χ™Χ•Χ“', 12, DARK_TEXT),
('β€’ Χ›Χ‘Χœ CAN ΧžΧœΧ•Χ€Χ£ מראש Χ‘Χ˜Χ‘Χ’Χͺ ΧžΧ’Χ Χ˜Χ™Χͺ', 12, DARK_TEXT),
('β€’ Χ›Χ‘Χœ DC β€” Χ§Χ¦Χ¨ ΧžΧ“Χ™ לל׀ף (Χ Χ§Χ•Χ“Χ” Χ€ΧͺΧ•Χ—Χ”)', 12, ORANGE, True),
('β€’ ΧžΧ•ΧžΧ Χ˜ Χ”Χ™Χ“Χ•Χ§: 24.5 NΒ·m', 12, DARK_TEXT),
('β€’ ΧœΧ•Χ•Χ“Χ Χ§Χ•Χ˜Χ‘Χ™Χ•Χͺ ΧœΧ€Χ Χ™ Χ—Χ™Χ‘Χ•Χ¨!', 12, RED, True),
], accent=TEAL)
add_card(slide, Inches(6.8), Inches(4.0), card_w, card_h,
'אחריוΧͺ Χ•Χ©Χ™Χ¨Χ•Χͺ', [
('β€’ Solis β€” RCS Solar Χ‘Χ’"מ', 12, DARK_TEXT),
('β€’ CNTE/Yoshopo β€” RCS Solar Χ‘Χ’"מ', 12, DARK_TEXT),
('β€’ 10 שנים גל ΧžΧžΧ™Χ¨ Χ•Χ‘Χ•ΧœΧœΧ”', 12, DARK_TEXT),
('β€’ Χ”ΧͺΧ§Χ Χͺ Χ€ΧΧ ΧœΧ™Χ β€” באחריוΧͺ Χ”ΧœΧ§Χ•Χ—', 12, DARK_TEXT),
], accent=GOLD)
# ═══════════════════════════════════════════════════════════
# SLIDE 7 β€” QA Open Items
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
add_text_box(slide, Inches(0.5), Inches(0.3), Inches(12), Inches(0.7),
'5. Χ‘Χ§Χ¨Χͺ איכוΧͺ β€” Χ Χ§Χ•Χ“Χ•Χͺ Χ€ΧͺΧ•Χ—Χ•Χͺ', font_size=28, color=ORANGE, bold=True)
add_shape(slide, Inches(0.5), Inches(0.95), Inches(2), Pt(3), fill_color=ORANGE, shape_type=MSO_SHAPE.RECTANGLE)
open_items = [
('Q1', 'RCD (Χ€Χ—Χͺ)', 'Χ”ΧžΧͺΧ§Χ™ΧŸ: לא Χ©ΧžΧ™Χ Χ›Χ¨Χ’Χ’. Χ™Χ•Χ‘Χ™Χ€Χ• RCBO אם Χ”Χ‘Χ•Χ“Χ§ Χ™Χ“Χ¨Χ•Χ©', 'Χ Χ“Χ—Χ” ΧœΧ‘Χ“Χ™Χ§Χ”. ΧžΧ•ΧžΧœΧ₯ מראש'),
('Q2', 'AFCI', 'ΧžΧ•Χ‘Χ Χ” Χ‘Χ‘Χ•ΧœΧ™Χ‘ Χ‘Χ¦Χ“ DC, Χ“Χ•Χ¨Χ© Χ”Χ€Χ’ΧœΧ” Χ™Χ“Χ Χ™Χͺ', 'ΧœΧ•Χ•Χ“Χ activation Χ‘Χ”ΧͺΧ§Χ Χ”'),
('Q3', 'SPD DC Χ—Χ‘Χ¨', 'SPD Χ‘Χ¦Χ“ AC Χ‘ΧœΧ‘Χ“. Χ€ΧΧ ΧœΧ™Χ חשו׀ים ΧœΧ‘Χ¨Χ§ Χ‘Χ¦Χ“ DC', 'ΧœΧ©Χ§Χ•Χœ SPD DC 1000Vdc'),
('Q4', 'Ferrite ΧœΧ›Χ‘Χœ Χ‘Χ•ΧœΧœΧ”', 'Χ›Χ‘Χœ DC Χ§Χ¦Χ¨ ΧžΧ“Χ™ לל׀ף. CAN ΧžΧœΧ•Χ€Χ£ מראש', 'ΧœΧ‘Χ¨Χ¨ ΧžΧ•Χœ CNTE β€” Χ Χ§Χ•Χ“Χ” Χ€ΧͺΧ•Χ—Χ”'),
]
add_table_slide(slide, Inches(0.5), Inches(1.2), Inches(12.3), 34,
['#', 'ממצא', 'ΧžΧ¦Χ‘', 'Χ€Χ’Χ•ΧœΧ” Χ Χ“Χ¨Χ©Χͺ'],
open_items, highlight_rows=[0, 1, 2, 3],
col_ratios=[0.5, 1.5, 4, 3])
# ═══════════════════════════════════════════════════════════
# SLIDE 8 β€” QA Verified
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
add_text_box(slide, Inches(0.5), Inches(0.3), Inches(12), Inches(0.7),
'5. Χ‘Χ§Χ¨Χͺ איכוΧͺ β€” Χ€Χ¨Χ™Χ˜Χ™Χ Χͺקינים', font_size=28, color=GREEN, bold=True)
add_shape(slide, Inches(0.5), Inches(0.95), Inches(2), Pt(3), fill_color=GREEN, shape_type=MSO_SHAPE.RECTANGLE)
verified = [
('Χ˜Χ•Χ€Χ•ΧœΧ•Χ’Χ™Χ”', 'Χ‘Χ“Χ¨ΧͺΧ™Χͺ (Series) β€” ΧΧ™ΧŸ CT. C40 ΧžΧ‘Χ€Χ™Χ§', 'אושר Χ’"Χ™ מΧͺΧ§Χ™ΧŸ βœ“'),
('Voc Χ‘Χ˜Χ¨Χ™Χ Χ’', '396V < 1000V, Χ‘ΧͺΧ•Χš MPPT 200–850V', 'βœ“ ΧͺΧ§Χ™ΧŸ'),
('Isc Χ‘Χ˜Χ¨Χ™Χ Χ’', '~18A < 20A ΧžΧ§Χ‘Χ™ΧžΧ•Χ', 'βœ“ ΧͺΧ§Χ™ΧŸ'),
('Χ”ΧͺאמΧͺ Χ‘Χ•ΧœΧœΧ”', 'CNTE HV 120–800V = Χ‘Χ•ΧœΧ™Χ‘ 120–800V', 'βœ“ ΧͺΧ§Χ™ΧŸ'),
('זרם Χ‘Χ•ΧœΧœΧ”', '50A = Χ‘Χ•ΧœΧ™Χ‘ 50A max', 'βœ“ ΧͺΧ§Χ™ΧŸ'),
('IP Rating', 'ΧžΧžΧ™Χ¨ IP66 + Χ‘Χ•ΧœΧœΧ” IP66', 'βœ“ ΧͺΧ§Χ™ΧŸ'),
('ΧͺΧ§Χ©Χ•Χ¨Χͺ BMS', 'CAN/RS485 Χͺואם', 'βœ“ ΧͺΧ§Χ™ΧŸ'),
('DC Switch ΧžΧ•Χ‘Χ Χ”', 'ΧžΧžΧ™Χ¨ + Χ‘Χ•ΧœΧœΧ” β€” לא Χ¦Χ¨Χ™Χš Χ—Χ™Χ¦Χ•Χ Χ™', 'אושר Χ’"Χ™ מΧͺΧ§Χ™ΧŸ βœ“'),
('ΧžΧ€Χ‘Χ§Χ™ C40', 'Χ‘Χ‘Χ“Χ¨ΧͺΧ™ Χ”ΧžΧžΧ™Χ¨ לא ΧžΧ•Χ©Χš ΧžΧ’Χ‘Χ¨ ΧœΧ¦Χ¨Χ™Χ›Χ” (3x40A)', 'אושר Χ’"Χ™ מΧͺΧ§Χ™ΧŸ βœ“'),
('Χ§Χ˜Χ‘Χ™Χ', 'יציאΧͺ ΧžΧžΧ™Χ¨: 4P. אחרי Χ‘Χ•Χ¨Χ¨: 3P. Backup: 3P', 'אושר Χ’"Χ™ מΧͺΧ§Χ™ΧŸ βœ“'),
('Zero Export', 'Χ‘Χ‘Χ“Χ¨ΧͺΧ™ β€” ΧΧ•Χ˜Χ•ΧžΧ˜Χ™, ללא CT', 'אושר Χ’"Χ™ מΧͺΧ§Χ™ΧŸ βœ“'),
('Χ˜Χ’Χ™Χ Χͺ Χ‘Χ•ΧœΧœΧ”', 'ΧžΧ‘Χ•ΧœΧΧ¨Χ™ Χ‘ΧœΧ‘Χ“ β€” לא ΧžΧ”Χ¨Χ©Χͺ', 'אושר Χ’"Χ™ מΧͺΧ§Χ™ΧŸ βœ“'),
]
add_table_slide(slide, Inches(0.5), Inches(1.2), Inches(12.3), 28,
['Χ€Χ¨Χ™Χ˜', 'Χ‘Χ“Χ™Χ§Χ”', 'Χͺוצאה'],
verified, col_ratios=[1.5, 4, 2])
# ═══════════════════════════════════════════════════════════
# SLIDE 9 β€” Execution Phase A+B
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '6. Χ”Χ Χ—Χ™Χ•Χͺ Χ‘Χ™Χ¦Χ•Χ’ β€” Χ©ΧœΧ‘ א\'+Χ‘\'')
# Warning
warn = add_shape(slide, Inches(0.5), Inches(1.1), Inches(12.3), Inches(0.5), fill_color=LIGHT_RED)
add_text_box(slide, Inches(0.7), Inches(1.15), Inches(12), Inches(0.4),
'Χ›Χœ Χ”Χ’Χ‘Χ•Χ“Χ” Χ”Χ—Χ©ΧžΧœΧ™Χͺ Χ—Χ™Χ™Χ‘Χͺ ΧœΧ”ΧͺΧ‘Χ¦Χ’ גל Χ™Χ“Χ™ Χ—Χ©ΧžΧœΧΧ™ ΧžΧ•Χ‘ΧžΧš. Χ’Χ‘Χ•Χ“Χ” גל DC Χ’Χ‘Χ•Χ” (Χ’Χ“ 800V) ΧžΧ‘Χ•Χ›Χ Χͺ!',
font_size=12, color=RED, bold=True)
add_text_box(slide, Inches(0.5), Inches(1.7), Inches(6), Inches(0.4),
'Χ©ΧœΧ‘ א\' β€” Χ”Χ›Χ Χ” Χ•Χ¨Χ›Χ©', font_size=16, color=NAVY, bold=True)
add_checklist_col(slide, Inches(0.7), Inches(2.1), [
('☐ אישור ΧͺΧ›Χ Χ™Χͺ ΧžΧ•Χœ Χ—Χ©ΧžΧœΧΧ™', 'Χ”ΧͺΧΧžΧ” לΧͺΧ§Χ Χ•Χͺ Χ•ΧœΧ“Χ¨Χ™Χ©Χ•Χͺ Χ”Χ™Χ™Χ©Χ•Χ‘'),
('☐ Χ¨Χ›Χ© רכיבים חברים', 'ABB C40 4P x1, ABB C40 3P x3, SPD AC Type 2, Hager 4P 40A'),
('☐ Χ¨Χ›Χ© Χ›Χ‘ΧœΧ™Χ', 'H1Z2Z2-K 6mmΒ², NYY-J 5G10, הארקה 16mmΒ². DC+CAN ΧžΧ’Χ™Χ’Χ™Χ גם Χ”Χ¦Χ™Χ•Χ“'),
('☐ Χ‘Χ™ΧžΧ•ΧŸ ΧžΧ™Χ§Χ•Χ', 'Χ§Χ™Χ¨ ΧžΧ•Χ¦Χœ, Χ’Χ•Χ‘Χ” 60+, אוורור 30/50 Χ‘"מ, Χ Χ’Χ™Χ© לΧͺΧ—Χ–Χ•Χ§Χ”'),
])
add_text_box(slide, Inches(6.8), Inches(1.7), Inches(6), Inches(0.4),
'Χ©ΧœΧ‘ Χ‘\' β€” Χ”ΧͺΧ§Χ Χ” ΧžΧ›Χ Χ™Χͺ', font_size=16, color=NAVY, bold=True)
add_checklist_col(slide, Inches(7), Inches(2.1), [
('☐ Χ§Χ•Χ Χ‘Χ˜Χ¨Χ•Χ§Χ¦Χ™Χ” גל Χ”Χ’Χ’', 'ΧžΧ‘Χ™ΧœΧ•Χͺ, Χ™Χ¦Χ™Χ‘Χ•Χͺ Χ¨Χ•Χ—, Χ©Χ™Χ€Χ•Χ’, ΧΧ˜Χ™ΧžΧ”'),
('☐ Χ”Χ¨Χ›Χ‘Χͺ 18 Χ€ΧΧ ΧœΧ™Χ', '2 Χ‘Χ˜Χ¨Χ™Χ Χ’Χ™Χ x 9, Χ—Χ™Χ‘Χ•Χ¨ Χ˜Χ•Χ¨Χ™, הארקΧͺ ΧžΧ‘Χ’Χ¨Χ•Χͺ'),
('☐ Χ”ΧͺΧ§Χ Χͺ ΧžΧžΧ™Χ¨', 'Solis S6-EH3P20K-H β€” ΧͺΧœΧ™Χ™Χ” + מ׀לב'),
('☐ Χ”ΧͺΧ§Χ Χͺ Χ‘Χ•ΧœΧœΧ”', 'CNTE 18.8kWh β€” Χ—Χ™Χ–Χ•Χ§ Χ§Χ™Χ¨ (~100 Χ§"Χ’)'),
('☐ ΧœΧ•Χ— ΧžΧ€Χ‘Χ§Χ™Χ', 'ΧžΧ€Χ‘Χ§Χ™Χ, SPD, Χ‘Χ•Χ¨Χ¨ ΧžΧ¦Χ‘Χ™Χ. Χ‘Χ™ΧžΧ•ΧŸ Χ‘Χ¨Χ•Χ¨'),
])
# ═══════════════════════════════════════════════════════════
# SLIDE 10 β€” Execution Phase C+D
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '6. Χ”Χ Χ—Χ™Χ•Χͺ Χ‘Χ™Χ¦Χ•Χ’ β€” Χ©ΧœΧ‘ Χ’\'+Χ“\'')
add_text_box(slide, Inches(0.5), Inches(1.1), Inches(6), Inches(0.4),
'Χ©ΧœΧ‘ Χ’\' β€” Χ›Χ‘Χ™ΧœΧ” וחיבורים', font_size=16, color=NAVY, bold=True)
add_checklist_col(slide, Inches(0.7), Inches(1.5), [
('☐ DC Χ€ΧΧ ΧœΧ™Χ β†’ ΧžΧžΧ™Χ¨', 'H1Z2Z2-K 6mmΒ², MC4. Χ™Χ©Χ™Χ¨Χ•Χͺ ΧœΧžΧžΧ™Χ¨. ΧœΧ•Χ•Χ“Χ Χ§Χ•Χ˜Χ‘Χ™Χ•Χͺ!'),
('☐ DC Χ‘Χ•ΧœΧœΧ”', 'Χ›Χ‘Χœ ΧžΧ’Χ™Χ’ גם Χ”Χ¦Χ™Χ•Χ“. ΧžΧ•ΧžΧ Χ˜ 24.5 NΒ·m. Χ‘Χ“Χ™Χ§Χͺ Χ§Χ•Χ˜Χ‘Χ™Χ•Χͺ!'),
('☐ BMS/CAN', 'ΧžΧ’Χ™Χ’ ΧžΧœΧ•Χ€Χ£ מראש Χ‘Χ˜Χ‘Χ’Χͺ ΧžΧ’Χ Χ˜Χ™Χͺ'),
('☐ AC Grid', 'NYY-J 5G10 β†’ SPD β†’ MCB C40 4P β†’ Χ‘Χ•Χ¨Χ¨ β†’ Χ”ΧͺΧ€Χ¦ΧœΧ•Χͺ'),
('☐ AC Backup', 'NYY-J 5G10 β†’ MCB C40 3P β†’ Χ’Χ•ΧžΧ‘Χ™Χ חיוניים'),
('☐ Χ—Χ™Χ‘Χ•Χ¨ Χ¨Χ©Χͺ', 'Χ‘Χ•Χ¨Χ¨ β†’ MCB C40 3P β†’ ΧžΧ•Χ Χ” β†’ Χ¨Χ©Χͺ'),
('☐ הארקה', '16mmΒ² Cu: ΧžΧžΧ™Χ¨+Χ‘Χ•ΧœΧœΧ”+ΧžΧ‘Χ Χ”+Χ€ΧΧ ΧœΧ™Χ β†’ ΧΧœΧ§Χ˜Χ¨Χ•Χ“Χ”'),
])
add_text_box(slide, Inches(6.8), Inches(1.1), Inches(6), Inches(0.4),
'Χ©ΧœΧ‘ Χ“\' β€” Χ‘Χ“Χ™Χ§Χ•Χͺ ΧœΧ€Χ Χ™ Χ”Χ€Χ’ΧœΧ”', font_size=16, color=NAVY, bold=True)
add_checklist_col(slide, Inches(7), Inches(1.5), [
('☐ Voc Χ‘Χ˜Χ¨Χ™Χ Χ’', '~396V Β±5%, Χ”Χ€Χ¨Χ© <5% Χ‘Χ™ΧŸ Χ‘Χ˜Χ¨Χ™Χ Χ’Χ™Χ'),
('☐ Isc Χ‘Χ˜Χ¨Χ™Χ Χ’', '~18A Χ‘Χ©ΧžΧ© ΧžΧœΧΧ”, ΧžΧ•Χ“Χ“ DC rated'),
('☐ Χ§Χ•Χ˜Χ‘Χ™Χ•Χͺ DC', '+ ל-+, – ל-–. Χ—Χ™Χ‘Χ•Χ¨ Χ”Χ€Χ•Χš = Χ”Χ¨Χ‘ ΧžΧžΧ™Χ¨!'),
('☐ Χ‘Χ™Χ“Χ•Χ“ DC', 'ΧžΧ’Χ¨: >1MΞ© Χ‘Χ™ΧŸ +/– ΧœΧΧ“ΧžΧ”'),
('☐ Χ¨Χ¦Χ™Χ€Χ•Χͺ הארקה', '<0.5Ξ© ΧžΧ›Χœ ΧžΧ‘Χ’Χ¨Χͺ ל׀ב הארקה'),
('☐ מΧͺΧ— Χ‘Χ•ΧœΧœΧ”', '120–800V, SOC ΧžΧ™Χ Χ™ΧžΧœΧ™ ~20%'),
('☐ ΧͺΧ§Χ©Χ•Χ¨Χͺ BMS', 'ΧžΧžΧ™Χ¨ ΧžΧ–Χ”Χ” Χ‘Χ•ΧœΧœΧ”, SOC/מΧͺΧ—/טמ׀\''),
('☐ ΧžΧ€Χ‘Χ§Χ™Χ', 'Χ”Χ€Χ’ΧœΧ”/Χ Χ™ΧͺΧ•Χ§ Χ™Χ“Χ Χ™ של Χ›Χœ מ׀בק'),
('☐ מΧͺΧ— AC', '~400V Χ‘Χ™ΧŸ ׀אזוΧͺ, ~230V ׀אזה-Χ Χ™Χ™Χ˜Χ¨Χœ'),
])
# ═══════════════════════════════════════════════════════════
# SLIDE 11 β€” Execution Phase E+F
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, LIGHT_BG)
section_header(slide, '6. Χ”Χ Χ—Χ™Χ•Χͺ Χ‘Χ™Χ¦Χ•Χ’ β€” Χ©ΧœΧ‘ Χ”\'+Χ•\'')
add_text_box(slide, Inches(0.5), Inches(1.1), Inches(6), Inches(0.4),
'Χ©ΧœΧ‘ Χ”\' β€” Χ”Χ€Χ’ΧœΧ” ראשונה (Commissioning)', font_size=16, color=NAVY, bold=True)
add_checklist_col(slide, Inches(0.7), Inches(1.5), [
('☐ Χ”Χ€Χ’ΧœΧ” ΧœΧ€Χ™ Χ‘Χ“Χ¨', '1. DC switch Χ‘Χ•ΧœΧœΧ” β†’ 2. DC switch ΧžΧžΧ™Χ¨ (PV) β†’ 3. AC β†’ 4. ΧžΧžΧ™Χ¨'),
('☐ Χ”Χ’Χ“Χ¨Χ•Χͺ ΧžΧžΧ™Χ¨', 'BT+APP: Χ‘Χ•Χ’ Χ‘Χ•ΧœΧœΧ” (Lithium/CAN), ΧžΧ¦Χ‘: Zero Export, ΧͺΧ“Χ¨, מΧͺΧ—'),
('☐ Χ”Χ€Χ’ΧœΧͺ AFCI', 'activation required β€” Χ”Χ’Χ Χͺ Χ§Χ©Χͺ DC'),
('☐ Χ”Χ’Χ“Χ¨Χͺ Zero Export', 'וידוא Χ©ΧΧ™ΧŸ ייצוא לרשΧͺ. ΧœΧ•Χ•Χ“Χ Χ©ΧžΧžΧ™Χ¨ ΧžΧ•Χ¨Χ™Χ“ Χ™Χ™Χ¦Χ•Χ¨ Χ›Χ©ΧΧ™ΧŸ Χ¦Χ¨Χ™Χ›Χ”'),
('☐ Χ‘Χ“Χ™Χ§Χͺ Backup', 'Χ Χ™ΧͺΧ•Χ§ Χ¨Χ©Χͺ β†’ Χ’Χ•ΧžΧ‘Χ™Χ חיוניים גובדים <10ms'),
('☐ WiFi/Ethernet', 'Χ—Χ™Χ‘Χ•Χ¨ ΧœΧ Χ™Χ˜Χ•Χ¨ β€” SolisCloud'),
('☐ Χ Χ™Χ˜Χ•Χ¨ 24 Χ©Χ’Χ•Χͺ', 'Χ™Χ™Χ¦Χ•Χ¨, Χ˜Χ’Χ™Χ Χ”, Χ¦Χ¨Χ™Χ›Χ”, ייבוא. וידוא Zero Export!'),
])
add_text_box(slide, Inches(6.8), Inches(1.1), Inches(6), Inches(0.4),
'Χ©ΧœΧ‘ Χ•\' β€” Χ‘Χ™ΧžΧ•ΧŸ Χ•ΧͺΧ™Χ’Χ•Χ“', font_size=16, color=NAVY, bold=True)
add_checklist_col(slide, Inches(7), Inches(1.5), [
('☐ Χ‘Χ™ΧžΧ•ΧŸ ΧžΧ€Χ‘Χ§Χ™Χ', '"PV 1", "PV 2", "Χ‘Χ•ΧœΧœΧ”", "AC", "Χ¨Χ©Χͺ", "Χ’Χ•ΧžΧ‘Χ™Χ", "Backup"'),
('☐ שלט Χ›Χ™Χ‘Χ•Χ™ חירום', '"1. Χ›Χ‘Χ” DC switch גל ΧžΧžΧ™Χ¨ Χ•Χ‘Χ•ΧœΧœΧ” 2. Χ ΧͺΧ§ AC"'),
('☐ ΧͺΧ™Χ’Χ•Χ“', 'ΧͺΧ›Χ Χ™Χͺ, אישורים, Χ‘Χ¨Χ™ΧΧœΧ™Χ™Χ, ΧͺΧžΧ•Χ Χ•Χͺ'),
('☐ ΧžΧ‘Χ™Χ¨Χ” ΧœΧœΧ§Χ•Χ—', 'Χ”Χ“Χ¨Χ›Χ”: ΧΧ€ΧœΧ™Χ§Χ¦Χ™Χ”, ΧžΧ¦Χ‘Χ™Χ, חירום, ΧͺΧ—Χ–Χ•Χ§Χ”'),
])
# Key differences box
box = add_shape(slide, Inches(6.8), Inches(3.4), Inches(5.9), Inches(2.8), fill_color=WHITE, line_color=NAVY)
add_multiline_box(slide, Inches(7), Inches(3.5), Inches(5.5), Inches(2.6), [
('Χ”Χ‘Χ“ΧœΧ™Χ ΧžΧ’Χ¨Χ‘Χ” Χ§Χ•Χ“ΧžΧͺ β€” Χ›Χ™Χ‘Χ•Χ™ חירום:', 14, NAVY, True),
('', 6),
('Χ”Χ€Χ’ΧœΧ”/Χ›Χ™Χ‘Χ•Χ™ Χ“Χ¨Χš DC switch ΧžΧ•Χ‘Χ Χ”', 13, DARK_TEXT, True),
('(לא DC Isolators חיצוניים)', 12, GRAY),
('', 6),
('1. Χ›Χ‘Χ” DC switch גל Χ”ΧžΧžΧ™Χ¨', 13, RED, True),
('2. Χ›Χ‘Χ” DC switch גל Χ”Χ‘Χ•ΧœΧœΧ”', 13, RED, True),
('3. Χ ΧͺΧ§ מ׀בק AC', 13, RED, True),
('', 6),
('⚠ Χ€ΧΧ ΧœΧ™Χ ΧžΧžΧ©Χ™Χ›Χ™Χ ΧœΧ™Χ™Χ¦Χ¨ מΧͺΧ— (~396V)', 12, RED),
('Χ›Χœ Χ’Χ•Χ“ Χ™Χ© אור β€” לא ΧœΧ’Χ’Χͺ Χ‘-MC4!', 12, RED, True),
])
# ═══════════════════════════════════════════════════════════
# SLIDE 12 β€” Closing
# ═══════════════════════════════════════════════════════════
slide = prs.slides.add_slide(prs.slide_layouts[6])
set_slide_bg(slide, NAVY)
add_shape(slide, Inches(5.5), Inches(3.3), Inches(2.5), Pt(3), fill_color=GOLD, shape_type=MSO_SHAPE.RECTANGLE)
add_text_box(slide, Inches(1), Inches(2), Inches(11), Inches(1),
'ΧͺΧ›Χ Χ™Χͺ Χ—Χ©ΧžΧœΧ™Χͺ β€” Χ—Χ•Χ•Χͺ יאיר', font_size=36, color=WHITE, bold=True, alignment=PP_ALIGN.CENTER)
add_text_box(slide, Inches(1), Inches(2.8), Inches(11), Inches(0.5),
'ΧžΧ’Χ¨Χ›Χͺ Χ‘Χ•ΧœΧΧ¨Χ™Χͺ Χ”Χ™Χ‘Χ¨Χ™Χ“Χ™Χͺ | 11.16kWp | 18.8kWh | Zero Export', font_size=20, color=RGBColor(0xA8, 0xD8, 0xEA), alignment=PP_ALIGN.CENTER)
add_multiline_box(slide, Inches(1), Inches(3.8), Inches(11), Inches(2), [
('Χ˜Χ•Χ€Χ•ΧœΧ•Χ’Χ™Χ” Χ‘Χ“Χ¨ΧͺΧ™Χͺ | ללא CT | DC switch ΧžΧ•Χ‘Χ Χ” | C40', 14, GOLD, True, PP_ALIGN.CENTER),
('', 10),
('מבמך Χ–Χ” Χ”Χ•Χ›ΧŸ ΧœΧ¦Χ¨Χ›Χ™ ΧͺΧ›Χ Χ•ΧŸ Χ‘ΧœΧ‘Χ“', 14, RGBColor(0xCD, 0xDE, 0xEE), False, PP_ALIGN.CENTER),
('ואינו ΧžΧ”Χ•Χ•Χ” ΧͺΧ›Χ Χ™Χͺ Χ—Χ©ΧžΧœΧ™Χͺ Χ¨Χ©ΧžΧ™Χͺ.', 14, RGBColor(0xCD, 0xDE, 0xEE), False, PP_ALIGN.CENTER),
('Χ™Χ© ΧœΧ•Χ•Χ“Χ גם Χ—Χ©ΧžΧœΧΧ™ ΧžΧ•Χ‘ΧžΧš ΧœΧ€Χ Χ™ Χ‘Χ™Χ¦Χ•Χ’.', 14, RGBColor(0xCD, 0xDE, 0xEE), True, PP_ALIGN.CENTER),
('', 10),
('ΧΧœΧ™ ב׀רא | מרΧ₯ 2026', 16, GOLD, False, PP_ALIGN.CENTER),
])
# ── Save ──
output_path = os.path.expanduser('~/Documents/GitHub/Baseline/ΧͺΧ›Χ Χ™Χͺ_Χ—Χ©ΧžΧœΧ™Χͺ_Χ—Χ•Χ•Χͺ_יאיר.pptx')
prs.save(output_path)
print(f'Saved: {output_path}')
print(f'Slides: {len(prs.slides)}')