420 lines
15 KiB
Python
420 lines
15 KiB
Python
import rieter_ekalk as rek
|
|
import pandas as pd
|
|
import argparse
|
|
import os
|
|
import configparser
|
|
|
|
|
|
order_dienstleistungen = [
|
|
"Pflichtenheft_Autom_Schnittstellen",
|
|
|
|
"Erstellung_Steuerungslayout",
|
|
"Schaltplanerstellung_incl_Korrekturen",
|
|
"Projektkoordination",
|
|
"Materialdispo",
|
|
"Abstimmung_mit_E_Werkstatt",
|
|
"Erstellen_E_Montageunterlagen",
|
|
|
|
"PC_Installation",
|
|
"Oberfläche_Simulation",
|
|
"SPS_Test_im_Haus_Simulation",
|
|
"Bedienerhandbuch",
|
|
"SPS_Doku",
|
|
"PC_Doku",
|
|
"Summe_Dienstleistungen_Hardwareplanung",
|
|
|
|
"Schaltschrankbau",
|
|
"Unterverteilerbau",
|
|
"Klemmkastenbau_je_2h",
|
|
"Bedientableaubau",
|
|
"Vormontage_im_Haus",
|
|
"Summe_Dienstleistungen_Elektrowerkstatt",
|
|
|
|
"Summe_Dienstleistungen_in_LL",
|
|
]
|
|
order_ergebnisse = [
|
|
"E_Werkstatt",
|
|
"Schaltschrankbau_extern_Mehrkosten",
|
|
"Dienstleistung_in_LL",
|
|
"Pflichtenheft",
|
|
"SPS_Programmierung",
|
|
"PC_Programmierung_Visualisierung",
|
|
"Montage_elektrisch",
|
|
"Inbetriebnahmetest_Hardware_durch_Montage",
|
|
"SPS_Inbetriebsetzung",
|
|
"PC_Inbetriebsetzung",
|
|
"Inbetriebnahmeunterstützung_durch_Montage",
|
|
"Dokumentation",
|
|
"Bedienungsanleitung_Emmert",
|
|
"Schulung_vor_Ort_beim_Kunden",
|
|
"Abnahme",
|
|
"SPS_Anlagenbetreuung",
|
|
"PC_Anlagenbetreuung",
|
|
"Anlagenbetreuung_durch_Montage",
|
|
"GESAMT",
|
|
]
|
|
order_hardware = [
|
|
"schaltschrankgehaeuse_b1x1200_zubehoer",
|
|
"schaltschrankgehaeuse_b2x800_zubehoer",
|
|
"schaltschrankgehaeuse_b1x1200+1x800_zubehoer",
|
|
"sps_simatic_s7_cpu315_2_pn_dp",
|
|
"speicherkarte_fuer_sps_512_kb",
|
|
"sps_simatic_s7_cpu317_2_pn_dp",
|
|
"speicherkarte_fuer_sps2_mb",
|
|
"sps_simatic_s7_1515_2",
|
|
"sps_simatic_s7_1517_3",
|
|
"sps_simatic_s7_1518_4",
|
|
"sps_et200_1512sp",
|
|
"memory_card_2_gb",
|
|
"et200_sp_ea_ebene",
|
|
"netzwerk_fernwartung",
|
|
"abgang_400v",
|
|
"abgang_24_v",
|
|
"anlagenrechner",
|
|
"anlagenrechner_ohne_bildschirm",
|
|
"pulteinbau_monitor_srline_rflat_24fhd",
|
|
"kurzhubtastatur_kbt06_mit_touchpad_uslayout",
|
|
"netzwerk_display_adapter_lindy",
|
|
"zusaetzlicher_bildschirm",
|
|
"schaltschrank",
|
|
"unterverteiler_fuer_1neuenhauser_pm",
|
|
"unterverteiler_fuer_1flyer",
|
|
"unterverteiler_fuer_2flyer",
|
|
"unterverteiler_fuer_1flyer_f40_mit_integrierter_putzmaschine",
|
|
"unterverteiler_fuer_2flyer_f40_mit_integrierter_putzmaschine",
|
|
"unterverteiler_fuer_puffer",
|
|
"unterverteiler_fuer_5_rsm_fa",
|
|
"korrektur_5_rsm_zusaetzlich_im_unterverteiler",
|
|
"unterverteiler_fuer_10_rsm_fa",
|
|
"korrektur_10_rsm_zusaetzlich_im_unterverteiler",
|
|
"unterverteiler_fuer_3_rsm_fa_mit_umfahrung_steckbar",
|
|
"korrektur_3_rsm_zusaetzlich_im_unterverteiler",
|
|
"unterverteiler_fuer_4_rsm_direct",
|
|
"korrektur_4_rsm_zusaetzlich_im_unterverteiler",
|
|
"unterverteiler_fuer_12_rsm_direct",
|
|
"korrektur_12_rsm_zusaetzlich_im_unterverteiler",
|
|
"unterverteiler_fuer_8_rsm_direct",
|
|
"korrektur_8_rsm_direct_zusaetzlich_im_unterverteiler",
|
|
"busverteiler_6_rsm_direct",
|
|
"korrektur_6_rsm_zusaetzlich_im_busverteiler",
|
|
"busverteiler_8_rsm_direct",
|
|
"korrektur_8_rsm_zusaetzlich_im_busverteiler",
|
|
"antrieb_unidirektional_halbleiter",
|
|
"antrieb_bidirektional_halbleiter",
|
|
"antrieb_unidirektional_schuetz",
|
|
"antrieb_bidirektional_schuetz",
|
|
"motorschutzschalter",
|
|
"wendeschuetzschaltung",
|
|
"frequenzumrichter",
|
|
"bedienstation_1fach_kpl",
|
|
"bedienst_2fach_wechs_bcd_10f",
|
|
"bedienstation_2fach_kpl",
|
|
"halter_bedientableau_2fach",
|
|
"bedienstation_3fach_kpl",
|
|
"halter_bedientableau_3fach",
|
|
"bedienstation_4fach_kpl",
|
|
"halter_bedientableau_4fach",
|
|
"bedienstation_6fach_kpl",
|
|
"halter_bedienstation_6fach",
|
|
"drucktaster_automatische_umfahrung",
|
|
"halter_fuer_drucktaster",
|
|
"ET200_SP",
|
|
"et_200sp_bundle_profinet_im_155_6pn_st_ba_2xrj45",
|
|
"korrektur_et_200sp_bundle_profinet_im_155_6pn_st_ba_2xrj45",
|
|
"et200_sp_eingangskarte_8_de",
|
|
"korrektur_et200_sp_eingangskarte_8_de",
|
|
"et200_sp_eingangskarte_16_de",
|
|
"et200_sp_eingangskarte_8_do",
|
|
"korrektur_et200_sp_eingangskarte_8_do",
|
|
"et200_sp_eingangskarte_16_do",
|
|
"et200_sp_base_unit_neue_last_mit_potKlemmen",
|
|
"korrektur_et200_sp_base_unit_neue_last_mit_potKlemmen",
|
|
"et200_sp_base_unit_links_gebrueckt_mit_pot_klemmen",
|
|
"et200_sp_base_unit_neue_last",
|
|
"korrektur_et200_sp_base_unit_neue_last",
|
|
"et200_sp_base_unit_links_gebrueckt",
|
|
"korrektur_et200_sp_base_unit_links_gebrueckt",
|
|
"SLIO",
|
|
"et_200sp_bundle_profinet_im_155_6pn_st_ba_2xrj45_SLIO",
|
|
"korrektur_et_200sp_bundle_profinet_im_155_6pn_st_ba_2xrj45_SLIO",
|
|
"slio_eingangskarte_4_de",
|
|
"korrektur_slio_eingangskarte_4_de",
|
|
"slio_eingangskarte_8_de",
|
|
"korrektur_slio_eingangskarte_8_de",
|
|
"slio_ausgangskarte_4_do",
|
|
"korrektur_slio_ausgangskarte_4_do",
|
|
"slio_ausgangskarte_8_do",
|
|
"korrektur_slio_ausgangskarte_8_do",
|
|
"slio_power_modul",
|
|
"korrektur_slio_power_modul",
|
|
"slio_4_x_dc_24v_4_x_dc_0v",
|
|
"korrektur_slio_4_x_dc_24v_4_x_dc_0v",
|
|
"slio_8_x_dc_24v",
|
|
"slio_8_x_dc_0v",
|
|
"korrektur_slio_8_x_dc_0v",
|
|
"movimot_fu_mit_anschaltung",
|
|
"sensor_optisch_traverse",
|
|
"sensorhalter_ohne_sensor",
|
|
"reflexionslichtschranke_rsm_direct",
|
|
"stoppersensor_induktiv_mit_halter",
|
|
"sensor_spulenpruefung_voll_leer",
|
|
"seilzugschalter",
|
|
"seil_fuer_seilzugschalter",
|
|
"blitzleuchte",
|
|
"spulenumsetzstation",
|
|
"sensorkabel_je_20m",
|
|
"stopper_weichenkabel_je_5m",
|
|
"motorkabel_je_30m",
|
|
"kabelpritschen_leitern_200_60",
|
|
"kabelpritsche_rsm_100_60",
|
|
"kabelpritsche_rsm_50_35",
|
|
"klemmkasten_rsm",
|
|
"klemmkasten_direct_in_rsm",
|
|
"erdung",
|
|
"kleinteile_rohre_schellen_kabelbinder_ect",
|
|
"kabel_fuer_klemmkasten_und_bts_60m",
|
|
"kabel_fuer_1fach_bts_zug_wechseln",
|
|
"zuleitung_75_m_unterverteiler_4x4mm2_400vac",
|
|
"zuleitung_75_m_unterverteiler_12x4mm2_24_vdc",
|
|
"korrektur_zuleitung_75_m_unterverteiler_12x4mm2_24_vdc",
|
|
"zuleitung_75_m_unterverteiler_12x2_5mm2_24_vdc",
|
|
"korrektur_zuleitung_75_m_unterverteiler_12x2_5mm2_24_vdc",
|
|
"zuleitung_55_m_klemmkasten_rsm_mitte_14g1_5_mm",
|
|
"zuleitung_55_m_klemmkasten_rsm_mitte_14g1_0_mm",
|
|
"profinetkabel",
|
|
"korrektur_profinetkabel",
|
|
"schnittstellen_8x1mm2_30m",
|
|
"Summe_Landsberg",
|
|
"Summe_vorOrt",
|
|
"Summe_gesamt",
|
|
]
|
|
order_eas = [
|
|
'bedienstation_1fach_Not_Aus',
|
|
'bedienstation_einfach_Zug_Wechseln',
|
|
'bedienstation_automatische_Umfahrung',
|
|
'bedienstation_zweifach_Wechs_BCD_10f',
|
|
'bedienstation_zweifach_Not_Aus_Reset',
|
|
'bedienst_dreifach',
|
|
'bedienst_vierfach',
|
|
'bedienst_sechsfach',
|
|
'EAs_Unterverteiler_direct',
|
|
|
|
'Sensor_Traversenabfrage_optisch',
|
|
'Reflexionslichtschranke_RSM_DIRECT',
|
|
'Sensor induktiv Flyer+PM',
|
|
'Seilzugschalter',
|
|
|
|
'Weiche',
|
|
'Weiche_nach_PM_bipolar',
|
|
'gemeinsame_Weichenrueckstellung',
|
|
'Dreifach_Weiche_DIRECT',
|
|
'Kreuzungsweiche',
|
|
'Stopper',
|
|
'Ventil_RA_3_2_abhebbar',
|
|
'Ventil_Doppelstreckenantrieb_5_2_abhebbar',
|
|
'Blitzleuchte_Stoerung',
|
|
|
|
'Schnittstelle_Flyer_ElectroJet',
|
|
'Schnittstelle_Putzmaschine_Neuhauser',
|
|
'FEldbux_UV_EinAusgang',
|
|
|
|
'Spulenumsetzstation',
|
|
|
|
'RA_unidirektional',
|
|
'RA_unidirektional_abhebbar',
|
|
'RA_unidirektional_mit_gemeinsamer_Wendung',
|
|
'RA_unidirektional_ohne_SPS_Ansteuerung',
|
|
'RA_bidirektional',
|
|
'RA_bidirektional_abhebbar',
|
|
'RA_bidirektional_abhebbar_gemeinsWend',
|
|
'RA_bidirektional_ohne_SPS_Ansteuerung',
|
|
'RA_in_RSM_bidirektional',
|
|
'Doppelstreckenantrieb',
|
|
'Doppelstreckenantriebgemeinsame_Wendung',
|
|
'gemeinsame_Wendung',
|
|
'Frequenzumrichter',
|
|
|
|
'Summe Komponenten',
|
|
'Summe Komponenten inkcl. Reserve',
|
|
]
|
|
class cfg():
|
|
"""
|
|
Liest die config-Datei ein, in der Stückpreise und Zeiteinheiten pro Bauteil wie in der rieter_ekalk Excel-Datei verwendet angegeben sind, und schreibt sie in ein Dictionary.
|
|
"""
|
|
def __init__(self, path="Sivas_Daten.cfg"):
|
|
"""
|
|
:param path: Die config-Datei, in der Stückpreise und Zeiteinheiten der jeweiligen Bauteile aufgelistet sind z.B.[HW_Einzelpreise]
|
|
# Schaltschrank Einzelpreis
|
|
schaltschrankgehaeuse_b1x800_zubehoer = 2000
|
|
"""
|
|
self._hasConfig = True
|
|
if os.path.exists(path):
|
|
self._cfg = configparser.ConfigParser(inline_comment_prefixes="#")
|
|
self._cfg.optionxform = str
|
|
self._cfg.read_file(open(path))
|
|
else:
|
|
self._hasConfig = False
|
|
self._cfg = None
|
|
|
|
def exists(self):
|
|
return self._hasConfig
|
|
|
|
def isfloat(self, num):
|
|
try:
|
|
float(num)
|
|
return True
|
|
except ValueError:
|
|
return False
|
|
|
|
def getTypedDict(self, section:str):
|
|
"""
|
|
Schreibt die Zuordnungen von Bauteil:Stückpreis/Zeiteinheit (je nach gewählter Überschrift) aus der config-Datei in ein Dictionary.
|
|
:param section: Überschrift in der config-Datei z.B. "HW_Einzelpreise"
|
|
"""
|
|
if section not in self._cfg.sections():
|
|
return dict()
|
|
res = dict()
|
|
for key, val in self._cfg.items(section):
|
|
if val.lower() in ['true']:
|
|
res[key] =True
|
|
elif val.lower() in ['false']:
|
|
res[key] =False
|
|
elif val.startswith("-"):
|
|
res[key] = float(val)
|
|
elif self.isfloat(val):
|
|
res[key] = float(val)
|
|
else:
|
|
res[key] = val
|
|
return res
|
|
|
|
|
|
def run_calc(infile, outfile, SivasConfig):
|
|
|
|
|
|
infileCfg = cfg(infile)
|
|
|
|
Anzahl_MG = infileCfg.getTypedDict("allgemein")
|
|
rsm_direct_eingabe = infileCfg.getTypedDict("rsm_direct")
|
|
rsm_fa_eingabe = infileCfg.getTypedDict("rsm_fa")
|
|
flyer_f40_eingabe = infileCfg.getTypedDict("flyer_f40")
|
|
neuenhauser_eingabe = infileCfg.getTypedDict("neuenhauser")
|
|
flyer_eingabe = infileCfg.getTypedDict("flyer")
|
|
verbindungsstrecken_w_eingabe = infileCfg.getTypedDict("verbindungsstrecken_w")
|
|
puffer_eingabe = infileCfg.getTypedDict("puffer")
|
|
turm_eingabe = infileCfg.getTypedDict("turm")
|
|
mg = rek.MG(Anzahl_MG,
|
|
rsm_direct=rsm_direct_eingabe,
|
|
rsm_fa=rsm_fa_eingabe,
|
|
flyer_f40=flyer_f40_eingabe,
|
|
neuenhauser=neuenhauser_eingabe,
|
|
flyer=flyer_eingabe,
|
|
verbindungsstrecken_w=verbindungsstrecken_w_eingabe,
|
|
puffer=puffer_eingabe,
|
|
turm=turm_eingabe)
|
|
|
|
|
|
anStr = SivasConfig.getTypedDict("Antriebsstrom")
|
|
cosPhi = SivasConfig.getTypedDict("cos phi")
|
|
al = rek.Anschlussl(anStr, cosPhi)
|
|
Anzahl_AL ={}
|
|
al.calc(Anzahl_AL, mg)
|
|
# self.assertEqual(al._ANZAHL.get("Anzahl_Motor"), 48)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("Summe_Strom_Motor"), 26.4)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("Summe_Strom_Motor_SPS_Peripherie"), 29.4)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("GZF"), 16.2)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("Res"), 1.62)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("Gesamtstrom"), 17.82)
|
|
# self.assertAlmostEqual(al._Anschlussspannung, 400)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("Leistung"), 12.345696)
|
|
# self.assertAlmostEqual(al._ANZAHL.get("Gesamtanschlussleistung"), 13)
|
|
|
|
Anzahl_EAS = infileCfg.getTypedDict("EAS")
|
|
eas = rek.EA(Anzahl_EAS, mg)
|
|
dEas = eas.getSEAs(order_eas)
|
|
dEas['Summe Komponenten'] = [eas.gesamt_E(), eas.gesamt_A()]
|
|
dEas['Summe Komponenten inkcl. Reserve'] = [eas.gesamt_E_incl_reserve(), eas.gesamt_A_incl_reserve()]
|
|
|
|
df_temp = pd.DataFrame.from_dict(data=dEas, orient='index', columns=['S.E', 'S.A'])
|
|
df_eas = pd.DataFrame(data=df_temp, index=order_eas)
|
|
|
|
Anzahl_HW = infileCfg.getTypedDict("HW")
|
|
|
|
|
|
hwep = SivasConfig.getTypedDict("HW_Einzelpreise")
|
|
hwhp = SivasConfig.getTypedDict("HW_Zeiten Hardwareplanung")
|
|
hwzew = SivasConfig.getTypedDict("HW_Zeiten Elektro-Werkstatt")
|
|
|
|
hw = rek.HW(hwep, hwhp, hwzew)
|
|
hw.calc(Anzahl_HW, mg, eas)
|
|
hardware = hw.get_anzahl()
|
|
hardware["Summe_vorOrt"] = hw.summe_vorort()
|
|
hardware["Summe_gesamt"] = hw.summe_gesamt()
|
|
hardware["Summe_Landsberg"] = hw.summe_in_LL()
|
|
hardware["Zeiten_Hardwareplanung"] = hw.summe_h_zeiten_hardwareplanung()
|
|
hardware["Zeiten_Unterverteiler_Werkstatt"] = hw.summe_h_unterverteiler_e_werkstatt()
|
|
df_temp = pd.DataFrame.from_dict(data=hardware, orient='index', columns=['Strück'])
|
|
df_hardware = pd.DataFrame(data=df_temp, index=order_hardware)
|
|
|
|
emoz = SivasConfig.getTypedDict("Elektro-Montagezeiten")
|
|
emo = rek.EMO(emoz)
|
|
emo.calc(eas, hw, mg)
|
|
|
|
Anzahl_DL = infileCfg.getTypedDict("DL")
|
|
dl = rek.Dienstleistung(Anzahl_DL, hw)
|
|
dienstleistung = dl.get_hours()
|
|
dienstleistung["Summe_Dienstleistungen_Hardwareplanung"] = dl.stunden_diensleistung_hardwareplanung()
|
|
dienstleistung["Summe_Dienstleistungen_Elektrowerkstatt"] = dl.stunden_elektrowerkstatt()
|
|
dienstleistung["Summe_Dienstleistungen_in_LL"] = dl.summe_stunden_dienstleistung_in_landsberg()
|
|
df_temp = pd.DataFrame.from_dict(data=dienstleistung, orient='index', columns=['Aufwand [h]'])
|
|
df_dienst = pd.DataFrame(data=df_temp, index=order_dienstleistungen)
|
|
|
|
Anzahl_Ergebnis = infileCfg.getTypedDict("Ergebnis")
|
|
kph = SivasConfig.getTypedDict("Kosten pro h")
|
|
erg = rek.Ergebnis(kph)
|
|
erg.calc(Anzahl_Ergebnis, hw, dl, emo)
|
|
|
|
ergebnisse = erg.summary_costs(hw)
|
|
df_temp = pd.DataFrame.from_dict(data=ergebnisse, orient='index', columns=['Aufwand [€]'])
|
|
df_aufwand = pd.DataFrame(data=df_temp, index=order_ergebnisse)
|
|
|
|
|
|
#df = pd.DataFrame.from_dict(data=dienstleistung, orient='index', columns=['Dienstleistungen'])
|
|
|
|
with pd.ExcelWriter(outfile) as writer:
|
|
df_aufwand.to_excel(writer, sheet_name='Kostenaufstellung')
|
|
df_hardware.to_excel(writer, sheet_name='Hardware')
|
|
df_dienst.to_excel(writer, sheet_name='Dienstleistungen')
|
|
df_eas.to_excel(writer, sheet_name='EAs')
|
|
# TODO Mengengerüst, EMO, ev. Anschlussleistung und Ausgangsstrom
|
|
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser(description='calculation of a system according to Bös', prog='ecalc')
|
|
parser.add_argument('-i', '--infile', action='store', help='name of the input file', default="jayjay.cfg")
|
|
parser.add_argument('-o', '--outfile', action='store', help='name of the output .xlsx file. If none given, name of the input file is used.')
|
|
parser.add_argument('-c', '--config', action='store', help='name of the config file inside of cfg folder to use. Default is Sivas_Daten.cfg', default="Sivas_Daten.cfg")
|
|
|
|
args = parser.parse_args()
|
|
sivasCfgFilePath = os.path.join(os.environ.get('ECALC_CFG'), args.config)
|
|
RieterConfig = cfg(sivasCfgFilePath)
|
|
|
|
inFilePath = os.path.join(os.environ.get('ECALC_WORK'), args.infile)
|
|
if os.path.isfile(inFilePath):
|
|
if args.outfile:
|
|
outPath = os.path.join(os.environ.get('ECALC_WORK'), args.outfile)
|
|
else:
|
|
(fname, ext) = os.path.splitext(args.infile)
|
|
outPath = os.path.join(os.environ.get('ECALC_WORK'), fname + '.xlsx')
|
|
run_calc(inFilePath, outPath, RieterConfig)
|
|
else:
|
|
print("no such file in ECALC_WORK")
|
|
# os.environ.get('ECALC_BIN')
|
|
# os.environ.get('ECALC_WORK')
|
|
# os.environ.get('ECALC_CFG')
|
|
# os.environ.get('ECALC_LIB')
|
|
|
|
|
|
|
|
|
|
|